From 67d261ab378fa9166ee6e0c31b7cb4e32a019925 Mon Sep 17 00:00:00 2001 From: garret Date: Sun, 25 Feb 2024 23:01:13 +0000 Subject: get rid of dependencycontrol bullshit there is no sense in me keeping it around when all it does is add faff to writing the script add useless noise to the filenames/paths and enforces its opinions upon me which i dont agree with and all for absolutely ZERO reason since i don't even have a feed in the first place if you want to take my scripts and package them into a dependencycontrol feed, you are more than welcome to do so, provided you comply with the terms of the licence. but your life is going to be a little bit harder i'm afraid, sorry about that. i will keep all the script_namespace, depctrl registration and such around for the time being (removing it is >effort) --- a-b.lua | 87 +++++++++++++++ append-comment.lua | 45 ++++++++ audio-clipper.lua | 129 +++++++++++++++++++++++ chapters.lua | 94 +++++++++++++++++ comment selection.lua | 21 ++++ ctrl-c-ctrl-v.lua | 90 ++++++++++++++++ dupe-and-comment.lua | 124 ++++++++++++++++++++++ em-dash.lua | 49 +++++++++ garret.depctrl_config.lua | 211 +++++++++++++++++++++++++++++++++++++ karaoke2alpha.lua | 70 ++++++++++++ light-purge.lua | 46 ++++++++ macros/audio-clipper.lua | 129 ----------------------- macros/comment selection.lua | 21 ---- macros/em-dash.lua | 49 --------- macros/garret.a-b.lua | 87 --------------- macros/garret.append-comment.lua | 45 -------- macros/garret.chapters.lua | 94 ----------------- macros/garret.ctrl-c-ctrl-v.lua | 90 ---------------- macros/garret.depctrl_config.lua | 211 ------------------------------------- macros/garret.dupe-and-comment.lua | 124 ---------------------- macros/garret.karaoke2alpha.lua | 70 ------------ macros/garret.restyler.lua | 68 ------------ macros/garret.select-comments.lua | 33 ------ macros/garret.shenanigans.lua | 81 -------------- macros/garret.sylsplitter.lua | 43 -------- macros/garret.timings_copier.lua | 54 ---------- macros/light-purge.lua | 46 -------- macros/pos2an.lua | 69 ------------ macros/scenebleed.lua | 35 ------ macros/songtimer.lua | 38 ------- pos2an.lua | 69 ++++++++++++ restyler.lua | 68 ++++++++++++ scenebleed.lua | 35 ++++++ select-comments.lua | 33 ++++++ shenanigans.lua | 81 ++++++++++++++ songtimer.lua | 38 +++++++ sylsplitter.lua | 43 ++++++++ timings_copier.lua | 54 ++++++++++ 38 files changed, 1387 insertions(+), 1387 deletions(-) create mode 100644 a-b.lua create mode 100644 append-comment.lua create mode 100644 audio-clipper.lua create mode 100644 chapters.lua create mode 100644 comment selection.lua create mode 100644 ctrl-c-ctrl-v.lua create mode 100644 dupe-and-comment.lua create mode 100644 em-dash.lua create mode 100644 garret.depctrl_config.lua create mode 100644 karaoke2alpha.lua create mode 100644 light-purge.lua delete mode 100644 macros/audio-clipper.lua delete mode 100644 macros/comment selection.lua delete mode 100644 macros/em-dash.lua delete mode 100644 macros/garret.a-b.lua delete mode 100644 macros/garret.append-comment.lua delete mode 100644 macros/garret.chapters.lua delete mode 100644 macros/garret.ctrl-c-ctrl-v.lua delete mode 100644 macros/garret.depctrl_config.lua delete mode 100644 macros/garret.dupe-and-comment.lua delete mode 100644 macros/garret.karaoke2alpha.lua delete mode 100644 macros/garret.restyler.lua delete mode 100644 macros/garret.select-comments.lua delete mode 100644 macros/garret.shenanigans.lua delete mode 100644 macros/garret.sylsplitter.lua delete mode 100644 macros/garret.timings_copier.lua delete mode 100644 macros/light-purge.lua delete mode 100644 macros/pos2an.lua delete mode 100644 macros/scenebleed.lua delete mode 100644 macros/songtimer.lua create mode 100644 pos2an.lua create mode 100644 restyler.lua create mode 100644 scenebleed.lua create mode 100644 select-comments.lua create mode 100644 shenanigans.lua create mode 100644 songtimer.lua create mode 100644 sylsplitter.lua create mode 100644 timings_copier.lua diff --git a/a-b.lua b/a-b.lua new file mode 100644 index 0000000..45f133f --- /dev/null +++ b/a-b.lua @@ -0,0 +1,87 @@ +script_name = "A-B" +script_description = "makes checking pre-timing possible." +script_author = "garret" +script_version = "3.0.0" +script_namespace = "garret.a-b" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +if haveDepCtrl then + depctrl = DependencyControl { + --feed="TODO", + } +end + +local function switch_indicator(i) + if i == "a" then + return "b" + elseif i == "b" then + return "a" + end +end + +local function strip_tags(text) + return text:gsub("{[^}]-}","") +end + +local function get_indicator(letter, actor) + local indicator + if actor == "" then + indicator = letter + else + indicator = actor.." "..letter + end + return indicator +end + +local function escape_pattern(txt) + local magic_chars = "%^%$%(%)%%.%[%]%*%+%-%?" + return txt:gsub("(["..magic_chars.."])", "%%%1") +end + +local function main(sub, sel) + local i = "a" + for _,li in ipairs(sel) do + local line = sub[li] + local indicator = get_indicator(i, line.actor) + + if line.text == "" then + line.text = indicator + elseif strip_tags(line.text) == "" then + line.text = line.text .. indicator -- apply tags + end + + sub[li] = line + i = switch_indicator(i) + end + aegisub.set_undo_point(script_name) +end + +local function undo(sub, sel) + local i = "a" + for _,li in ipairs(sel) do + local line = sub[li] + local indicator = get_indicator(i, line.actor) + + if line.text == indicator then + line.text = "" + else + local escaped = escape_pattern(indicator) + line.text = line.text:gsub(escaped, "") + end + sub[li] = line + i = switch_indicator(i) + end +end + +local macros = { + {"Add indicators", script_description, main}, + {"Clean up","Gets rid of the indicators once you've adjusted the lines", 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 diff --git a/append-comment.lua b/append-comment.lua new file mode 100644 index 0000000..f8cc92b --- /dev/null +++ b/append-comment.lua @@ -0,0 +1,45 @@ +script_name = "Append Comment" +script_description = "{ts do all the work pls kthxbye}" +script_author = "garret" +script_version = "2.0.0" +script_namespace = "garret.append-comment" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +if haveDepCtrl then + depctrl = DependencyControl { + --feed="TODO", + } +end + +local function main(sub, sel) + local dialog_config= + { + { + class="label", + x=0,y=0,width=1,height=1, + label="Comment:" + }, + { + class="textbox",name="msg", + x=0,y=1,width=10,height=5, + value="" + } + } + local button, results = aegisub.dialog.display(dialog_config) + if button ~= false then + for _, i in ipairs(sel) do + local line = sub[i] + local msg = results.msg:gsub("\n", "}{") + line.text = line.text.." {"..msg.."}" + sub[i] = line + end + else + aegisub.cancel() + end +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/audio-clipper.lua b/audio-clipper.lua new file mode 100644 index 0000000..fbab298 --- /dev/null +++ b/audio-clipper.lua @@ -0,0 +1,129 @@ +script_name = "Audio Clipper" +script_description = "Extracts audio from the selected line(s).\nNeeds ffmpeg." +script_author = "garret" +script_version = "1.1.3" + +function err(msg) + aegisub.dialog.display({{class = "label", label = msg}}, {"OK"}, {close = "OK"}) + aegisub.cancel() +end + +function get_vid_dir() + local aud_dir = aegisub.decode_path("?audio") + local vid_dir = aegisub.decode_path("?video") + if aud_dir ~= "?audio" then + return aud_dir + elseif vid_dir ~= "?video" then -- if there is not, in fact, a video + return vid_dir + else + return nil + end +end + +function get_vid() + local aud = aegisub.project_properties().audio_file -- try get the audio first, if it's loaded separately + local vid = aegisub.project_properties().video_file + if aud ~= "" then + return aud + elseif vid ~= "" then + return vid + else + return nil + end +end + +function get_format(copy, format, custom) + if copy == true then -- if we do want to copy + if format == "" then -- format is the thing from the dropdown + err("Need a format!") + elseif format == "AAC" then -- these are the most common audio formats i've seen + return "m4a" + elseif format == "Opus" then + return "opus" + elseif format == "FLAC" then + return "flac" elseif format == "Custom" then -- but I am not all-knowing, so you can put your own + return custom + end + else -- if we don't want to copy (i.e. we've pressed "Just make it FLAC") + return "flac" + end +end + +function make_out_path(out_path) + local lfs = require "aegisub.lfs" + if out_path == "" then + err("Need an output path!") + end + lfs.mkdir(out_path) + return out_path +end + +function extract_audio(in_path, start_time, end_time, out_path, name, extension, copy) + if copy == true then + os.execute('ffmpeg -ss '..start_time..'ms -to '..end_time..'ms -i "'..in_path..'" -codec copy -vn "'..out_path..name..'.'..extension..'" -y') + -- takes the video as input, copies the streams, but doesn't include video. sets it to start at the start of the selection, and end at the end of it. outputs to our chosen out path with our chosen name and extension. overwrites anything with the same name. + elseif copy == false then + os.execute('ffmpeg -ss '..start_time..'ms -to '..end_time..'ms -i "'..in_path..'" -vn "'..out_path..name..'.'..extension..'" -y') + -- same as above, but doesn't copy the stream (transcodes to flac) + end +end + +function loop(subs, sel, in_path, out_path, extension, copy, delay) + aegisub.progress.title("Extracting Audio") + local progress = 0 + local progress_increment = 100 / #sel -- increment by this for every line, and the bar will eventually reach 100 + for x, i in ipairs(sel) do -- x is the position of the line in our selection, i is the position in the whole sub file + if aegisub.progress.is_cancelled() then -- if you press the cancel button + aegisub.cancel() -- it stops (mind-blowing, i know) + end + aegisub.progress.set(progress) + local line = subs[i] + local start_time = line.start_time + delay + local end_time = line.end_time + delay + aegisub.progress.task("Extracting line "..x) + extract_audio(in_path, start_time, end_time, out_path, x, extension, copy) + progress = progress + progress_increment + end + aegisub.progress.set(100) -- in case it didn't reach 100 on its own +end + + +function gui(subs, sel) + local in_path = get_vid() + local out_path = get_vid_dir() + if in_path == nil or out_path == nil then -- if no video is loaded + in_path = "No audio/video loaded. Specify a path." + out_path = in_path -- both the same error message + else + out_path = out_path.."/audioclipper_output/" -- make the out path the one we actually want + end + + local get_input={{class="label",x=0,y=0,label="Input's audio format:"},{class="dropdown",name="format",x=0,y=1,width=2,height=1,items={"AAC","Opus","FLAC","Custom"},value="Audio Format",hint="If you don't know, you should probably press \"Just make it FLAC\", or use mka."},{class="label",x=0,y=2,label="Custom Extension:"},{class="edit",name="custom",x=1,y=2,value="mka",hint="You'll probably be fine with mka, because matroska can contain pretty much anything"},{class="label",x=0,y=3,label="Delay (ms):"},{class="intedit",name="delay",x=1,y=3,value=0,hint="to prevent timing fuckery with weird raws"},{class="label",x=0,y=4,label="Input path:"},{class="edit",name="in_path",x=0,y=5,width=2,height=1,value=in_path,hint="where the audio comes from"},{class="label",x=0,y=6,label="Output path (will be created if it doesn't already exist):"},{class="edit",name="out_path",x=0,y=7,width=2,height=1,value=out_path,hint="where the audio goes"}} + local pressed, results = aegisub.dialog.display(get_input, {"Cancel", "OK", "Just make it FLAC"}) + -- there's probably something that can detect the format automatically, but I do not know what it is. + if pressed == "Cancel" then + aegisub.cancel() + elseif pressed == "OK" then + do_copy = true + elseif pressed == "Just make it FLAC" then + do_copy = false + end + local extension = get_format(do_copy, results.format, results.custom) -- gets file extension + local delay = results.delay + in_path = results.in_path + out_path = make_out_path(results.out_path) + loop(subs, sel, in_path, out_path, extension, do_copy, delay) +end + +function non_gui(subs, sel) -- no gui, so you can bind it to a hotkey + local vid = get_vid() + if vid == nil then + err("Need an input!\nSpecify a path in the GUI, or load one in aegisub.") + else + loop(subs, sel, get_vid(), make_out_path(get_vid_dir().."/audioclipper_output/"), 'flac', false, 0) + end + -- sets sane defaults (takes the audio from the video file, and outputs to /the/video/dir/audioclipper_output/. transcodes to flac. no delay) +end + +aegisub.register_macro(script_name, script_description, gui) +aegisub.register_macro(": Non-GUI macros :/"..script_name..": Just make it FLAC", script_description, non_gui) -- same section as unanimated's scripts diff --git a/chapters.lua b/chapters.lua new file mode 100644 index 0000000..bcb78b9 --- /dev/null +++ b/chapters.lua @@ -0,0 +1,94 @@ +script_name = "Chapter Generator" +script_description = "Makes XML chapters for matroska." +script_author = "garret" +script_version = "2.1.0" +script_namespace = "garret.chapters" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") + +if haveDepCtrl then + depctrl = DependencyControl { + --feed="TODO", + } +end + +--local config = simpleconf.get_config(aegisub.decode_path(config_dir.."/"..script_namespace..".conf"), {language = "eng", language_ietf = "en"}) +local config = {language = "eng", language_ietf = "en"} + + +function ms_to_human(start) -- From Significance + local timecode=math.floor(start/1000) + local tc1=math.floor(timecode/60) + local tc2=timecode%60 + local tc3=start%1000 + local tc4="00" + if tc2==60 then tc2=0 tc1=tc1+1 end + if tc1>119 then tc1=tc1-120 tc4="02" end + if tc1>59 then tc1=tc1-60 tc4="01" end + if tc1<10 then tc1="0"..tc1 end + if tc2<10 then tc2="0"..tc2 end + if tc3<100 then tc3="0"..tc3 end + linetime=tc4..":"..tc1..":"..tc2.."."..tc3 + if linetime=="00:00:00.00" then linetime="00:00:00.033" end + return linetime +end + +function get_sane_path() + script_path = aegisub.decode_path("?script") + audio_path = aegisub.decode_path("?audio") + video_path = aegisub.decode_path("?video") + if script_path ~= "?script" then + return script_path + elseif video_path ~= "?video" then + return video_path + elseif audio_path ~= "?audio" then + return audio_path + else + return "" + end +end + +function get_user_path(default_dir) + local path = aegisub.dialog.save("Save Chapter File", default_dir, "chapters.xml", "XML files|*.xml|All Files|*", false) + return path +end + +function main(sub) + local times = {} + local names = {} + for i=1,#sub do + local line = sub[i] + if line.class == "dialogue" then + local fx = line.effect + if fx:match("[Cc]hapter") or fx:match("[Cc]hptr") or fx:match("[Cc]hap") then + line.comment = true + table.insert(times, line.start_time) + table.insert(names, line.text) + sub[i] = line + end + end + end + aegisub.set_undo_point(script_name) + local chapters = "\n\n\n \n" + for j, k in ipairs(times) do + local humantime = ms_to_human(k) + local name = names[j] + chapters = chapters.." \n "..humantime.."\n \n "..name.."\n "..config.language_ietf.."\n "..config.language.."\n \n \n" + end + chapters = chapters.." \n" + sane_path = get_sane_path() + path = get_user_path(sane_path) + if path ~= nil then + local chapfile = io.open(path, "w") + chapfile:write(chapters) + chapfile:close() + else + aegisub.cancel() + end +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/comment selection.lua b/comment selection.lua new file mode 100644 index 0000000..e06c853 --- /dev/null +++ b/comment selection.lua @@ -0,0 +1,21 @@ +script_name = "Comment selection" +script_description = "comment (add {} around) highlighted text in a line" +script_author = "garret" +script_version = "0.1.0" + +local function have_selection_funcs() + return aegisub.gui and aegisub.gui.get_selection +end + +local function main(sub, sel, act) + local line = sub[act] + local start, end_ = aegisub.gui.get_selection() + local txt = line.text:sub(1, start -1 ).."{"..line.text:sub(start, end_-1).."}"..line.text:sub(end_, #line.text) + line.text = txt + sub[act] = line + aegisub.set_undo_point(script_name) +end + +if have_selection_funcs() then + aegisub.register_macro(script_name, script_description, main) +end diff --git a/ctrl-c-ctrl-v.lua b/ctrl-c-ctrl-v.lua new file mode 100644 index 0000000..04c994d --- /dev/null +++ b/ctrl-c-ctrl-v.lua @@ -0,0 +1,90 @@ +script_name = "Consistency Assistant" +script_description = "ctrl-c ctrl-v and now ctrl-o" +script_version = "1.2.0" +script_author = "garret" +script_namespace = "garret.ctrl-c-ctrl-v" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +local parser +if haveDepCtrl then + depctrl = DependencyControl({ + --feed="TODO", + { + { + "myaa.ASSParser", + version = "0.0.4", -- very sketch about this + url = "http://github.com/TypesettingTools/Myaamori-Aegisub-Scripts", + feed = "https://raw.githubusercontent.com/TypesettingTools/Myaamori-Aegisub-Scripts/master/DependencyControl.json", + optional = true, + }, + }, + }) + parser = depctrl:requireModules() +end + +--inspect = require "inspect" + +-- it looks more complicated than it is because of all the aegisub.log()s +local function main(sub, is_recursion) + local clipboard = {} + for i = 1, #sub do + local line = sub[i] + if line.class == "dialogue" then + local op, name = line.effect:match("ctrl%-([cvo]) ?([%S]*)") + if op == "o" and parser ~= "nil" then -- o = open. check for parser or it wont work + clipboard["__imports"] = clipboard["__imports"] or {} -- declare field + clipboard["__imports"][name] = import(line.text) + elseif line.comment ~= true then + if op == "c" then + aegisub.log(5, 5, "ctrl-c " .. name .. ": " .. line.text .. "\n") + clipboard[name] = clipboard[name] or {} + table.insert(clipboard[name], line) + elseif op == "v" and is_recursion ~= true then -- don't want to affect the imported files (useless) + -- have to specifically check ~= true because normally it'd be sel, which is a table of numbers (not nil/false) + local file, slash, capture = name:match("([^%s/]+)(/?)([%S]*)") -- match filename/capture + local clippings -- names = anything not a space or a / + aegisub.log(5, file.."/"..capture.."\n") + aegisub.log(5, "slash: "..slash.."\n") + if slash ~= "" and parser ~= nil then + clippings = clipboard["__imports"][file][capture] + aegisub.log(5, "clippings = clipboard[\"__imports\"][\""..file.."\"][\""..capture.."\"]\n") + else + clippings = clipboard[file] or {line} -- error handling if the clipboard doesnt exist or parser isnt there + aegisub.log(5, "clippings = clipboard[\""..file.."\"]\n") + end + aegisub.log(5, "ctrl-v " .. name .. ": " .. line.text .. "\n") +-- aegisub.log(5, inspect(clippings).."\n") + line.text = clippings[1].text + sub[i] = line + table.remove(clippings, 1) + end + end + end + aegisub.progress.set(i / #sub * 100) + end +-- aegisub.log(5, inspect(clipboard).."\n") + return clipboard +end + +function import(path) +--local function import(path) + if parser then + aegisub.log(5, "recursing\n") + local f = io.open(aegisub.decode_path(path), "r") + local sub = parser.parse_file(f).events + f:close() + local clipboard = main(sub, true) + aegisub.log(5, "recursion complete\n") + return clipboard + else + aegisub.log(1, "You don't appear to have myaa.ASSParser, which is required for including other files.\n") + aegisub.log(1, "The script will continue, but any includes you've specified won't work.\n") + return {} + end +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/dupe-and-comment.lua b/dupe-and-comment.lua new file mode 100644 index 0000000..16e2e97 --- /dev/null +++ b/dupe-and-comment.lua @@ -0,0 +1,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 diff --git a/em-dash.lua b/em-dash.lua new file mode 100644 index 0000000..c52aa1b --- /dev/null +++ b/em-dash.lua @@ -0,0 +1,49 @@ +script_name = "Em-dash" +script_description = "I do not have an em-dash key on my keyboard" +script_author = "garret" +script_version = "2.1.0" + +local em = "—" + +local function have_cursor_funcs() + return aegisub.gui and aegisub.gui.get_cursor and aegisub.gui.set_cursor +end + +local function insert(sub, sel, act) + local line = sub[act] + local pos = aegisub.gui.get_cursor() + local start = string.sub(line.text, 1, pos - 1) + local end_ = string.sub(line.text, pos) + line.text = start .. em .. end_ + aegisub.gui.set_cursor(pos + 1) + sub[act] = line +end + +local function append(sub, sel) + for si, li in ipairs(sel) do + local line = sub[li] + if string.sub(line.text, -1) == "-" then + line.text = line.text:sub(1, #line.text - 1) + end + line.text = line.text..em + sub[li] = line + end + aegisub.set_undo_point(script_name) +end + +local function replace(sub, sel) + for si, li in ipairs(sel) do + local line = sub[li] + local text = sub[li].text + text = text:gsub("%-%-",em) + line.text=text + sub[li] = line + end + aegisub.set_undo_point(script_name) +end + +aegisub.register_macro(script_name.."/Append", "Appends an Em-dash to the selected line(s)", append) +aegisub.register_macro(script_name.."/Replace", "Replaces -- with "..em, replace) +if have_cursor_funcs() then + aegisub.register_macro(script_name.."/Insert", "Inserts an em-dash at the cursor position", insert) +end diff --git a/garret.depctrl_config.lua b/garret.depctrl_config.lua new file mode 100644 index 0000000..ad3e663 --- /dev/null +++ b/garret.depctrl_config.lua @@ -0,0 +1,211 @@ +script_name="DepCtrl Global Config" +script_description="the future is now" +script_author = "garret" +script_version = "1.3.1" +script_namespace = "garret.depctrl_config" + +local DependencyControl = require("l0.DependencyControl") +local depctrl = DependencyControl {} + +local function get_bool(field, default) -- can't just do `field or default`, because the default might be true when field is false + if field == nil then + return default + else + return field + end +end + +local function get_log_level(num) + if num == 0 then return "0: Fatal" + elseif num == 1 then return "1: Error" + elseif num == 2 then return "2: Warning" + elseif num == 3 then return "3: Hint" + elseif num == 4 then return "4: Debug" + elseif num == 5 then return "5: Trace" end + return nil +end + +local function seconds_to_human(seconds) + -- adapted from https://stackoverflow.com/a/8211778 + local years = math.floor(seconds / 31536000) + local days = math.floor((seconds % 31536000) / 86400) + local hours = math.floor(((seconds % 31536000) % 86400) / 3600) + local minutes = math.floor((((seconds % 31536000) % 86400) % 3600) / 60) + seconds = (((seconds % 31536000) % 86400) % 3600) % 60 + --return years, days, hours, minutes, seconds + local timestamp = "" + if years ~= 0 then timestamp = timestamp..years.."y" end + if days ~= 0 then timestamp = timestamp..days.."d" end + if hours ~= 0 then timestamp = timestamp..hours.."h" end + if minutes ~= 0 then timestamp = timestamp..minutes.."m" end + if seconds ~= 0 then timestamp = timestamp..seconds.."s" end + return timestamp +end + +local function human_to_seconds(human) + -- im sure this is hideously inefficient + local years = (tonumber(human:match("(%d*)y")) or 0) * 31536000 + local days = (tonumber(human:match("(%d*)d")) or 0) * 86400 + local hours = (tonumber(human:match("(%d*)h")) or 0) * 3600 + local minutes = (tonumber(human:match("(%d*)m")) or 0) * 60 + local seconds = (tonumber(human:match("(%d*)s")) or 0) + local res = years + days + hours + minutes + seconds + return res +end + +local function get_human_filesize(bytes) + -- TODO + return bytes +end + +local function get_config(config) + local defaults = DependencyControl.config.defaults + local dialog = { + { class="checkbox", name="updaterEnabled", + x=0,y=0,width=2,height=1, + label = "Enable Auto-updater", + value=get_bool(config.updaterEnabled, defaults.updaterEnabled), + }, + { class="label", label="Update interval:", + x=0,y=1,width=1,height=1, + }, + { class="edit", name = "updateInterval", + x=1,y=1,width=1,height=1, + value = seconds_to_human(config.updateInterval or defaults.updateInterval) + }, + { class="label", label="Log Level:", + x=0,y=2,width=1,height=1, + }, + { class="dropdown", name="traceLevel", + x=1,y=2,width=1,height=1, + items={"0: Fatal", "1: Error", "2: Warning", "3: Hint", "4: Debug", "5: Trace"}, + value=get_log_level(config.traceLevel) or "3: Hint", + }, + { class="checkbox", name="dumpFeeds", + x=0,y=3,width=2,height=1, + label = "Dump updater feeds to your Aegsiub folder (debug)", + value=get_bool(config.dumpFeeds, defaults.dumpFeeds) + }, + { class="checkbox", name="tryAllFeeds", + x=0,y=4,width=2,height=1, + label = "Check all available feeds for an update", + value=get_bool(config.tryAllFeeds, defaults.tryAllFeeds) + }, + { class="label", label="Config directory to offer automation scripts:", + x=0,y=5,width=1,height=1 + }, + { class="edit", name="configDir", + text=config.configDir or defaults.configDir, + x=1,y=5,width=1,height=1 + }, + { class="checkbox", name="writeLogs", + x=0,y=6,width=1,height=1, + label = "Write log messages to:", + value=get_bool(config.writeLogs, true) + }, + { class="edit", name="logDir", + text=config.logDir or defaults.logDir, + x=1,y=6,width=1,height=1 + }, + { class="label", label= "?user means " .. aegisub.decode_path("?user"), + x=1,y=7,width=2,height=1 + }, + { class="label", label="Purge old updater log files when:", + x=0,y=8,width=2,height=1 + }, + { class="label", label="File count reaches:", + x=0,y=9,width=1,height=1 + }, + { class="intedit", name="logMaxFiles", + x=1,y=9,width=1,height=1, + value = config.logMaxFiles or defaults.logMaxFiles + }, + { class="label", label="File age reaches:", + x=0,y=10,width=1,height=1, + }, + { class="edit", name="logMaxAge", + x=1,y=10,width=1,height=1, + value = seconds_to_human(config.logMaxAge or defaults.logMaxAge) + }, + { class="label", label="Cumulative file size (in bytes) reaches:", + x=0,y=11,width=1,height=1, + }, + { class="intedit", name="logMaxSize", + x=1,y=11,width=1,height=1, + --value = get_human_filesize(config.logMaxSize or 10*(10^6)) + value = config.logMaxSize or defaults.logMaxSize + }, + } + local pressed, res = aegisub.dialog.display(dialog, {"Cancel", "Reset", "OK"}) + if pressed == "Cancel" then + aegisub.cancel() + elseif pressed == "Reset" then + return {} + end + res.traceLevel = tonumber(res.traceLevel:sub(1, 1)) + res.updateInterval = human_to_seconds(res.updateInterval) + res.logMaxAge = human_to_seconds(res.logMaxAge) + res.extraFeeds = config.extraFeeds + return res +end + +local function split_by_newline(list) + local strs = {} + for i in list:gmatch("[^\n]+") do + table.insert(strs, i) + end + return strs +end + +local function get_feeds(config) + local extraFeeds = config.extraFeeds or {} + + local feed_edit_string = table.concat(extraFeeds, "\n") or "" + + local dialog = { + { class="label", + x=0,y=0,width=1,height=1, + label = "Extra Feeds:", + }, + { class="textbox", name = "feeds", + x=0,y=1,width=20,height=15, + text = feed_edit_string + }, + } + + local pressed, res = aegisub.dialog.display(dialog) + if not pressed then aegisub.cancel() end + + config.extraFeeds = split_by_newline(res.feeds) + return config +end + +local function write_config(new) + for k, v in pairs(new) do + if (v == nil) -- allow nil, so the reset to defaults button works + or v ~= get_bool(DependencyControl.config.c[k], DependencyControl.config.defaults[k]) -- check it's not the current value anyway + then + -- changed, save + DependencyControl.config.c[k] = v + end + end + DependencyControl.config:write(true) + aegisub.log(3, "Done. You'll need to rescan your automation directory or restart aegisub for the changes to take effect.") +end + +local function change_config(modifier) -- i think i might be thinning out the soup a bit too much + DependencyControl.config:load() + local new_config = modifier(DependencyControl.config.c) + write_config(new_config) +end + +local function global_config() + change_config(get_config) +end + +local function extra_feeds() + change_config(get_feeds) +end + +depctrl:registerMacro("DependencyControl/Global Configuration", "Lets you change DependencyControl settings.", global_config) +depctrl:registerMacro("DependencyControl/Extra Feeds", "Lets you provide additional update feeds.", extra_feeds) diff --git a/karaoke2alpha.lua b/karaoke2alpha.lua new file mode 100644 index 0000000..51ff0c5 --- /dev/null +++ b/karaoke2alpha.lua @@ -0,0 +1,70 @@ +script_name = "K-Timing -> Alpha Timing" +script_description = "makes doing alpha timing significantly easier by getting rid of the part where you do alpha timing." +script_author = "garret" +script_version = "1.1.0" +script_namespace = "garret.karaoke2alpha" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +local util +if haveDepCtrl then + depctrl = DependencyControl { + --feed="TODO", + {"aegisub.util"} + } + util = depctrl:requireModules() +else + util = require 'aegisub.util' +end + +function get_visible(parsed_line, index) + local res = "" + for i=1,index do -- for every syl up to the current one + res = res..parsed_line[i].text -- add to the result + end + return res +end + +function get_invisible(parsed_line, index) + local res = "" + for i=index+1,#parsed_line do -- for every syl from the next one to the end + res = res..parsed_line[i].text -- add to result + end + return res +end + +function main(sub, sel) + for x=#sel,1,-1 do + local line=sub[sel[x]] + local parsed = aegisub.parse_karaoke_data(line) -- magic function that gets all the stuff about the karaoke + for i=1,#parsed do -- for every syl in the karaoke + visible = get_visible(parsed, i) + invisible = get_invisible(parsed, i) + if invisible ~= "" then -- if there's still invisible stuff left + text = visible.."{\\alpha&HFF&}"..invisible -- add an alpha tag and slap the invisible stuff on the end + else -- if it's all visible + text = visible -- don't need the alpha any more + end + local syl = parsed[i] + local new = util.copy(line) + new.text = text -- make a new line for this syl + -- set line start time + new.start_time = syl.start_time + line.start_time -- just the syl on its own returns the offset from the line + -- set line end time + if i ~= #parsed then -- if there's still invisible stuff left + new.end_time = syl.end_time + line.start_time -- end time is the syl's + else + new.end_time = line.end_time -- end time is the whole line's (i don't think this actually makes a difference but may as well) + end + sub.insert(sel[x] + i,new) -- add new lines (+1 line for first syl, +2 for 2nd syl, etc) + end + line.comment = true -- don't want to see the karaoke any more + sub[sel[x]]=line + end + aegisub.set_undo_point(script_name) +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/light-purge.lua b/light-purge.lua new file mode 100644 index 0000000..b139266 --- /dev/null +++ b/light-purge.lua @@ -0,0 +1,46 @@ +script_name = "TXT Cleanup" +script_description = "remove actors and/or linebreaks" +script_author = "garret" +script_version = "2.0.0" + +local function main(sub, conf) + for i = 1, #sub do + if sub[i].class == "dialogue" then + local line = sub[i] + if conf.purge_actors == true then + line.actor = "" + end + if conf.purge_linebreaks == true then + line.text = line.text:gsub(" *\\[Nn] *", " ") + end + sub[i] = line + end + end +end + +local function conf() + local conf = { + { + class = "checkbox", + name = "purge_actors", + x = 0, + y = 0, + width = 1, + height = 1, + label = "Remove Actors", + value = true, + }, + { + class = "checkbox", + name = "purge_linebreaks", + x = 0, + y = 1, + width = 1, + height = 1, + label = "Remove Linebreaks", + value = true, + }, + } + return conf +end +aegisub.register_filter(script_name, script_description, 1, main, conf) diff --git a/macros/audio-clipper.lua b/macros/audio-clipper.lua deleted file mode 100644 index fbab298..0000000 --- a/macros/audio-clipper.lua +++ /dev/null @@ -1,129 +0,0 @@ -script_name = "Audio Clipper" -script_description = "Extracts audio from the selected line(s).\nNeeds ffmpeg." -script_author = "garret" -script_version = "1.1.3" - -function err(msg) - aegisub.dialog.display({{class = "label", label = msg}}, {"OK"}, {close = "OK"}) - aegisub.cancel() -end - -function get_vid_dir() - local aud_dir = aegisub.decode_path("?audio") - local vid_dir = aegisub.decode_path("?video") - if aud_dir ~= "?audio" then - return aud_dir - elseif vid_dir ~= "?video" then -- if there is not, in fact, a video - return vid_dir - else - return nil - end -end - -function get_vid() - local aud = aegisub.project_properties().audio_file -- try get the audio first, if it's loaded separately - local vid = aegisub.project_properties().video_file - if aud ~= "" then - return aud - elseif vid ~= "" then - return vid - else - return nil - end -end - -function get_format(copy, format, custom) - if copy == true then -- if we do want to copy - if format == "" then -- format is the thing from the dropdown - err("Need a format!") - elseif format == "AAC" then -- these are the most common audio formats i've seen - return "m4a" - elseif format == "Opus" then - return "opus" - elseif format == "FLAC" then - return "flac" elseif format == "Custom" then -- but I am not all-knowing, so you can put your own - return custom - end - else -- if we don't want to copy (i.e. we've pressed "Just make it FLAC") - return "flac" - end -end - -function make_out_path(out_path) - local lfs = require "aegisub.lfs" - if out_path == "" then - err("Need an output path!") - end - lfs.mkdir(out_path) - return out_path -end - -function extract_audio(in_path, start_time, end_time, out_path, name, extension, copy) - if copy == true then - os.execute('ffmpeg -ss '..start_time..'ms -to '..end_time..'ms -i "'..in_path..'" -codec copy -vn "'..out_path..name..'.'..extension..'" -y') - -- takes the video as input, copies the streams, but doesn't include video. sets it to start at the start of the selection, and end at the end of it. outputs to our chosen out path with our chosen name and extension. overwrites anything with the same name. - elseif copy == false then - os.execute('ffmpeg -ss '..start_time..'ms -to '..end_time..'ms -i "'..in_path..'" -vn "'..out_path..name..'.'..extension..'" -y') - -- same as above, but doesn't copy the stream (transcodes to flac) - end -end - -function loop(subs, sel, in_path, out_path, extension, copy, delay) - aegisub.progress.title("Extracting Audio") - local progress = 0 - local progress_increment = 100 / #sel -- increment by this for every line, and the bar will eventually reach 100 - for x, i in ipairs(sel) do -- x is the position of the line in our selection, i is the position in the whole sub file - if aegisub.progress.is_cancelled() then -- if you press the cancel button - aegisub.cancel() -- it stops (mind-blowing, i know) - end - aegisub.progress.set(progress) - local line = subs[i] - local start_time = line.start_time + delay - local end_time = line.end_time + delay - aegisub.progress.task("Extracting line "..x) - extract_audio(in_path, start_time, end_time, out_path, x, extension, copy) - progress = progress + progress_increment - end - aegisub.progress.set(100) -- in case it didn't reach 100 on its own -end - - -function gui(subs, sel) - local in_path = get_vid() - local out_path = get_vid_dir() - if in_path == nil or out_path == nil then -- if no video is loaded - in_path = "No audio/video loaded. Specify a path." - out_path = in_path -- both the same error message - else - out_path = out_path.."/audioclipper_output/" -- make the out path the one we actually want - end - - local get_input={{class="label",x=0,y=0,label="Input's audio format:"},{class="dropdown",name="format",x=0,y=1,width=2,height=1,items={"AAC","Opus","FLAC","Custom"},value="Audio Format",hint="If you don't know, you should probably press \"Just make it FLAC\", or use mka."},{class="label",x=0,y=2,label="Custom Extension:"},{class="edit",name="custom",x=1,y=2,value="mka",hint="You'll probably be fine with mka, because matroska can contain pretty much anything"},{class="label",x=0,y=3,label="Delay (ms):"},{class="intedit",name="delay",x=1,y=3,value=0,hint="to prevent timing fuckery with weird raws"},{class="label",x=0,y=4,label="Input path:"},{class="edit",name="in_path",x=0,y=5,width=2,height=1,value=in_path,hint="where the audio comes from"},{class="label",x=0,y=6,label="Output path (will be created if it doesn't already exist):"},{class="edit",name="out_path",x=0,y=7,width=2,height=1,value=out_path,hint="where the audio goes"}} - local pressed, results = aegisub.dialog.display(get_input, {"Cancel", "OK", "Just make it FLAC"}) - -- there's probably something that can detect the format automatically, but I do not know what it is. - if pressed == "Cancel" then - aegisub.cancel() - elseif pressed == "OK" then - do_copy = true - elseif pressed == "Just make it FLAC" then - do_copy = false - end - local extension = get_format(do_copy, results.format, results.custom) -- gets file extension - local delay = results.delay - in_path = results.in_path - out_path = make_out_path(results.out_path) - loop(subs, sel, in_path, out_path, extension, do_copy, delay) -end - -function non_gui(subs, sel) -- no gui, so you can bind it to a hotkey - local vid = get_vid() - if vid == nil then - err("Need an input!\nSpecify a path in the GUI, or load one in aegisub.") - else - loop(subs, sel, get_vid(), make_out_path(get_vid_dir().."/audioclipper_output/"), 'flac', false, 0) - end - -- sets sane defaults (takes the audio from the video file, and outputs to /the/video/dir/audioclipper_output/. transcodes to flac. no delay) -end - -aegisub.register_macro(script_name, script_description, gui) -aegisub.register_macro(": Non-GUI macros :/"..script_name..": Just make it FLAC", script_description, non_gui) -- same section as unanimated's scripts diff --git a/macros/comment selection.lua b/macros/comment selection.lua deleted file mode 100644 index e06c853..0000000 --- a/macros/comment selection.lua +++ /dev/null @@ -1,21 +0,0 @@ -script_name = "Comment selection" -script_description = "comment (add {} around) highlighted text in a line" -script_author = "garret" -script_version = "0.1.0" - -local function have_selection_funcs() - return aegisub.gui and aegisub.gui.get_selection -end - -local function main(sub, sel, act) - local line = sub[act] - local start, end_ = aegisub.gui.get_selection() - local txt = line.text:sub(1, start -1 ).."{"..line.text:sub(start, end_-1).."}"..line.text:sub(end_, #line.text) - line.text = txt - sub[act] = line - aegisub.set_undo_point(script_name) -end - -if have_selection_funcs() then - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/em-dash.lua b/macros/em-dash.lua deleted file mode 100644 index c52aa1b..0000000 --- a/macros/em-dash.lua +++ /dev/null @@ -1,49 +0,0 @@ -script_name = "Em-dash" -script_description = "I do not have an em-dash key on my keyboard" -script_author = "garret" -script_version = "2.1.0" - -local em = "—" - -local function have_cursor_funcs() - return aegisub.gui and aegisub.gui.get_cursor and aegisub.gui.set_cursor -end - -local function insert(sub, sel, act) - local line = sub[act] - local pos = aegisub.gui.get_cursor() - local start = string.sub(line.text, 1, pos - 1) - local end_ = string.sub(line.text, pos) - line.text = start .. em .. end_ - aegisub.gui.set_cursor(pos + 1) - sub[act] = line -end - -local function append(sub, sel) - for si, li in ipairs(sel) do - local line = sub[li] - if string.sub(line.text, -1) == "-" then - line.text = line.text:sub(1, #line.text - 1) - end - line.text = line.text..em - sub[li] = line - end - aegisub.set_undo_point(script_name) -end - -local function replace(sub, sel) - for si, li in ipairs(sel) do - local line = sub[li] - local text = sub[li].text - text = text:gsub("%-%-",em) - line.text=text - sub[li] = line - end - aegisub.set_undo_point(script_name) -end - -aegisub.register_macro(script_name.."/Append", "Appends an Em-dash to the selected line(s)", append) -aegisub.register_macro(script_name.."/Replace", "Replaces -- with "..em, replace) -if have_cursor_funcs() then - aegisub.register_macro(script_name.."/Insert", "Inserts an em-dash at the cursor position", insert) -end diff --git a/macros/garret.a-b.lua b/macros/garret.a-b.lua deleted file mode 100644 index 45f133f..0000000 --- a/macros/garret.a-b.lua +++ /dev/null @@ -1,87 +0,0 @@ -script_name = "A-B" -script_description = "makes checking pre-timing possible." -script_author = "garret" -script_version = "3.0.0" -script_namespace = "garret.a-b" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -if haveDepCtrl then - depctrl = DependencyControl { - --feed="TODO", - } -end - -local function switch_indicator(i) - if i == "a" then - return "b" - elseif i == "b" then - return "a" - end -end - -local function strip_tags(text) - return text:gsub("{[^}]-}","") -end - -local function get_indicator(letter, actor) - local indicator - if actor == "" then - indicator = letter - else - indicator = actor.." "..letter - end - return indicator -end - -local function escape_pattern(txt) - local magic_chars = "%^%$%(%)%%.%[%]%*%+%-%?" - return txt:gsub("(["..magic_chars.."])", "%%%1") -end - -local function main(sub, sel) - local i = "a" - for _,li in ipairs(sel) do - local line = sub[li] - local indicator = get_indicator(i, line.actor) - - if line.text == "" then - line.text = indicator - elseif strip_tags(line.text) == "" then - line.text = line.text .. indicator -- apply tags - end - - sub[li] = line - i = switch_indicator(i) - end - aegisub.set_undo_point(script_name) -end - -local function undo(sub, sel) - local i = "a" - for _,li in ipairs(sel) do - local line = sub[li] - local indicator = get_indicator(i, line.actor) - - if line.text == indicator then - line.text = "" - else - local escaped = escape_pattern(indicator) - line.text = line.text:gsub(escaped, "") - end - sub[li] = line - i = switch_indicator(i) - end -end - -local macros = { - {"Add indicators", script_description, main}, - {"Clean up","Gets rid of the indicators once you've adjusted the lines", 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 diff --git a/macros/garret.append-comment.lua b/macros/garret.append-comment.lua deleted file mode 100644 index f8cc92b..0000000 --- a/macros/garret.append-comment.lua +++ /dev/null @@ -1,45 +0,0 @@ -script_name = "Append Comment" -script_description = "{ts do all the work pls kthxbye}" -script_author = "garret" -script_version = "2.0.0" -script_namespace = "garret.append-comment" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -if haveDepCtrl then - depctrl = DependencyControl { - --feed="TODO", - } -end - -local function main(sub, sel) - local dialog_config= - { - { - class="label", - x=0,y=0,width=1,height=1, - label="Comment:" - }, - { - class="textbox",name="msg", - x=0,y=1,width=10,height=5, - value="" - } - } - local button, results = aegisub.dialog.display(dialog_config) - if button ~= false then - for _, i in ipairs(sel) do - local line = sub[i] - local msg = results.msg:gsub("\n", "}{") - line.text = line.text.." {"..msg.."}" - sub[i] = line - end - else - aegisub.cancel() - end -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.chapters.lua b/macros/garret.chapters.lua deleted file mode 100644 index bcb78b9..0000000 --- a/macros/garret.chapters.lua +++ /dev/null @@ -1,94 +0,0 @@ -script_name = "Chapter Generator" -script_description = "Makes XML chapters for matroska." -script_author = "garret" -script_version = "2.1.0" -script_namespace = "garret.chapters" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") - -if haveDepCtrl then - depctrl = DependencyControl { - --feed="TODO", - } -end - ---local config = simpleconf.get_config(aegisub.decode_path(config_dir.."/"..script_namespace..".conf"), {language = "eng", language_ietf = "en"}) -local config = {language = "eng", language_ietf = "en"} - - -function ms_to_human(start) -- From Significance - local timecode=math.floor(start/1000) - local tc1=math.floor(timecode/60) - local tc2=timecode%60 - local tc3=start%1000 - local tc4="00" - if tc2==60 then tc2=0 tc1=tc1+1 end - if tc1>119 then tc1=tc1-120 tc4="02" end - if tc1>59 then tc1=tc1-60 tc4="01" end - if tc1<10 then tc1="0"..tc1 end - if tc2<10 then tc2="0"..tc2 end - if tc3<100 then tc3="0"..tc3 end - linetime=tc4..":"..tc1..":"..tc2.."."..tc3 - if linetime=="00:00:00.00" then linetime="00:00:00.033" end - return linetime -end - -function get_sane_path() - script_path = aegisub.decode_path("?script") - audio_path = aegisub.decode_path("?audio") - video_path = aegisub.decode_path("?video") - if script_path ~= "?script" then - return script_path - elseif video_path ~= "?video" then - return video_path - elseif audio_path ~= "?audio" then - return audio_path - else - return "" - end -end - -function get_user_path(default_dir) - local path = aegisub.dialog.save("Save Chapter File", default_dir, "chapters.xml", "XML files|*.xml|All Files|*", false) - return path -end - -function main(sub) - local times = {} - local names = {} - for i=1,#sub do - local line = sub[i] - if line.class == "dialogue" then - local fx = line.effect - if fx:match("[Cc]hapter") or fx:match("[Cc]hptr") or fx:match("[Cc]hap") then - line.comment = true - table.insert(times, line.start_time) - table.insert(names, line.text) - sub[i] = line - end - end - end - aegisub.set_undo_point(script_name) - local chapters = "\n\n\n \n" - for j, k in ipairs(times) do - local humantime = ms_to_human(k) - local name = names[j] - chapters = chapters.." \n "..humantime.."\n \n "..name.."\n "..config.language_ietf.."\n "..config.language.."\n \n \n" - end - chapters = chapters.." \n" - sane_path = get_sane_path() - path = get_user_path(sane_path) - if path ~= nil then - local chapfile = io.open(path, "w") - chapfile:write(chapters) - chapfile:close() - else - aegisub.cancel() - end -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.ctrl-c-ctrl-v.lua b/macros/garret.ctrl-c-ctrl-v.lua deleted file mode 100644 index 04c994d..0000000 --- a/macros/garret.ctrl-c-ctrl-v.lua +++ /dev/null @@ -1,90 +0,0 @@ -script_name = "Consistency Assistant" -script_description = "ctrl-c ctrl-v and now ctrl-o" -script_version = "1.2.0" -script_author = "garret" -script_namespace = "garret.ctrl-c-ctrl-v" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -local parser -if haveDepCtrl then - depctrl = DependencyControl({ - --feed="TODO", - { - { - "myaa.ASSParser", - version = "0.0.4", -- very sketch about this - url = "http://github.com/TypesettingTools/Myaamori-Aegisub-Scripts", - feed = "https://raw.githubusercontent.com/TypesettingTools/Myaamori-Aegisub-Scripts/master/DependencyControl.json", - optional = true, - }, - }, - }) - parser = depctrl:requireModules() -end - ---inspect = require "inspect" - --- it looks more complicated than it is because of all the aegisub.log()s -local function main(sub, is_recursion) - local clipboard = {} - for i = 1, #sub do - local line = sub[i] - if line.class == "dialogue" then - local op, name = line.effect:match("ctrl%-([cvo]) ?([%S]*)") - if op == "o" and parser ~= "nil" then -- o = open. check for parser or it wont work - clipboard["__imports"] = clipboard["__imports"] or {} -- declare field - clipboard["__imports"][name] = import(line.text) - elseif line.comment ~= true then - if op == "c" then - aegisub.log(5, 5, "ctrl-c " .. name .. ": " .. line.text .. "\n") - clipboard[name] = clipboard[name] or {} - table.insert(clipboard[name], line) - elseif op == "v" and is_recursion ~= true then -- don't want to affect the imported files (useless) - -- have to specifically check ~= true because normally it'd be sel, which is a table of numbers (not nil/false) - local file, slash, capture = name:match("([^%s/]+)(/?)([%S]*)") -- match filename/capture - local clippings -- names = anything not a space or a / - aegisub.log(5, file.."/"..capture.."\n") - aegisub.log(5, "slash: "..slash.."\n") - if slash ~= "" and parser ~= nil then - clippings = clipboard["__imports"][file][capture] - aegisub.log(5, "clippings = clipboard[\"__imports\"][\""..file.."\"][\""..capture.."\"]\n") - else - clippings = clipboard[file] or {line} -- error handling if the clipboard doesnt exist or parser isnt there - aegisub.log(5, "clippings = clipboard[\""..file.."\"]\n") - end - aegisub.log(5, "ctrl-v " .. name .. ": " .. line.text .. "\n") --- aegisub.log(5, inspect(clippings).."\n") - line.text = clippings[1].text - sub[i] = line - table.remove(clippings, 1) - end - end - end - aegisub.progress.set(i / #sub * 100) - end --- aegisub.log(5, inspect(clipboard).."\n") - return clipboard -end - -function import(path) ---local function import(path) - if parser then - aegisub.log(5, "recursing\n") - local f = io.open(aegisub.decode_path(path), "r") - local sub = parser.parse_file(f).events - f:close() - local clipboard = main(sub, true) - aegisub.log(5, "recursion complete\n") - return clipboard - else - aegisub.log(1, "You don't appear to have myaa.ASSParser, which is required for including other files.\n") - aegisub.log(1, "The script will continue, but any includes you've specified won't work.\n") - return {} - end -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.depctrl_config.lua b/macros/garret.depctrl_config.lua deleted file mode 100644 index ad3e663..0000000 --- a/macros/garret.depctrl_config.lua +++ /dev/null @@ -1,211 +0,0 @@ -script_name="DepCtrl Global Config" -script_description="the future is now" -script_author = "garret" -script_version = "1.3.1" -script_namespace = "garret.depctrl_config" - -local DependencyControl = require("l0.DependencyControl") -local depctrl = DependencyControl {} - -local function get_bool(field, default) -- can't just do `field or default`, because the default might be true when field is false - if field == nil then - return default - else - return field - end -end - -local function get_log_level(num) - if num == 0 then return "0: Fatal" - elseif num == 1 then return "1: Error" - elseif num == 2 then return "2: Warning" - elseif num == 3 then return "3: Hint" - elseif num == 4 then return "4: Debug" - elseif num == 5 then return "5: Trace" end - return nil -end - -local function seconds_to_human(seconds) - -- adapted from https://stackoverflow.com/a/8211778 - local years = math.floor(seconds / 31536000) - local days = math.floor((seconds % 31536000) / 86400) - local hours = math.floor(((seconds % 31536000) % 86400) / 3600) - local minutes = math.floor((((seconds % 31536000) % 86400) % 3600) / 60) - seconds = (((seconds % 31536000) % 86400) % 3600) % 60 - --return years, days, hours, minutes, seconds - local timestamp = "" - if years ~= 0 then timestamp = timestamp..years.."y" end - if days ~= 0 then timestamp = timestamp..days.."d" end - if hours ~= 0 then timestamp = timestamp..hours.."h" end - if minutes ~= 0 then timestamp = timestamp..minutes.."m" end - if seconds ~= 0 then timestamp = timestamp..seconds.."s" end - return timestamp -end - -local function human_to_seconds(human) - -- im sure this is hideously inefficient - local years = (tonumber(human:match("(%d*)y")) or 0) * 31536000 - local days = (tonumber(human:match("(%d*)d")) or 0) * 86400 - local hours = (tonumber(human:match("(%d*)h")) or 0) * 3600 - local minutes = (tonumber(human:match("(%d*)m")) or 0) * 60 - local seconds = (tonumber(human:match("(%d*)s")) or 0) - local res = years + days + hours + minutes + seconds - return res -end - -local function get_human_filesize(bytes) - -- TODO - return bytes -end - -local function get_config(config) - local defaults = DependencyControl.config.defaults - local dialog = { - { class="checkbox", name="updaterEnabled", - x=0,y=0,width=2,height=1, - label = "Enable Auto-updater", - value=get_bool(config.updaterEnabled, defaults.updaterEnabled), - }, - { class="label", label="Update interval:", - x=0,y=1,width=1,height=1, - }, - { class="edit", name = "updateInterval", - x=1,y=1,width=1,height=1, - value = seconds_to_human(config.updateInterval or defaults.updateInterval) - }, - { class="label", label="Log Level:", - x=0,y=2,width=1,height=1, - }, - { class="dropdown", name="traceLevel", - x=1,y=2,width=1,height=1, - items={"0: Fatal", "1: Error", "2: Warning", "3: Hint", "4: Debug", "5: Trace"}, - value=get_log_level(config.traceLevel) or "3: Hint", - }, - { class="checkbox", name="dumpFeeds", - x=0,y=3,width=2,height=1, - label = "Dump updater feeds to your Aegsiub folder (debug)", - value=get_bool(config.dumpFeeds, defaults.dumpFeeds) - }, - { class="checkbox", name="tryAllFeeds", - x=0,y=4,width=2,height=1, - label = "Check all available feeds for an update", - value=get_bool(config.tryAllFeeds, defaults.tryAllFeeds) - }, - { class="label", label="Config directory to offer automation scripts:", - x=0,y=5,width=1,height=1 - }, - { class="edit", name="configDir", - text=config.configDir or defaults.configDir, - x=1,y=5,width=1,height=1 - }, - { class="checkbox", name="writeLogs", - x=0,y=6,width=1,height=1, - label = "Write log messages to:", - value=get_bool(config.writeLogs, true) - }, - { class="edit", name="logDir", - text=config.logDir or defaults.logDir, - x=1,y=6,width=1,height=1 - }, - { class="label", label= "?user means " .. aegisub.decode_path("?user"), - x=1,y=7,width=2,height=1 - }, - { class="label", label="Purge old updater log files when:", - x=0,y=8,width=2,height=1 - }, - { class="label", label="File count reaches:", - x=0,y=9,width=1,height=1 - }, - { class="intedit", name="logMaxFiles", - x=1,y=9,width=1,height=1, - value = config.logMaxFiles or defaults.logMaxFiles - }, - { class="label", label="File age reaches:", - x=0,y=10,width=1,height=1, - }, - { class="edit", name="logMaxAge", - x=1,y=10,width=1,height=1, - value = seconds_to_human(config.logMaxAge or defaults.logMaxAge) - }, - { class="label", label="Cumulative file size (in bytes) reaches:", - x=0,y=11,width=1,height=1, - }, - { class="intedit", name="logMaxSize", - x=1,y=11,width=1,height=1, - --value = get_human_filesize(config.logMaxSize or 10*(10^6)) - value = config.logMaxSize or defaults.logMaxSize - }, - } - local pressed, res = aegisub.dialog.display(dialog, {"Cancel", "Reset", "OK"}) - if pressed == "Cancel" then - aegisub.cancel() - elseif pressed == "Reset" then - return {} - end - res.traceLevel = tonumber(res.traceLevel:sub(1, 1)) - res.updateInterval = human_to_seconds(res.updateInterval) - res.logMaxAge = human_to_seconds(res.logMaxAge) - res.extraFeeds = config.extraFeeds - return res -end - -local function split_by_newline(list) - local strs = {} - for i in list:gmatch("[^\n]+") do - table.insert(strs, i) - end - return strs -end - -local function get_feeds(config) - local extraFeeds = config.extraFeeds or {} - - local feed_edit_string = table.concat(extraFeeds, "\n") or "" - - local dialog = { - { class="label", - x=0,y=0,width=1,height=1, - label = "Extra Feeds:", - }, - { class="textbox", name = "feeds", - x=0,y=1,width=20,height=15, - text = feed_edit_string - }, - } - - local pressed, res = aegisub.dialog.display(dialog) - if not pressed then aegisub.cancel() end - - config.extraFeeds = split_by_newline(res.feeds) - return config -end - -local function write_config(new) - for k, v in pairs(new) do - if (v == nil) -- allow nil, so the reset to defaults button works - or v ~= get_bool(DependencyControl.config.c[k], DependencyControl.config.defaults[k]) -- check it's not the current value anyway - then - -- changed, save - DependencyControl.config.c[k] = v - end - end - DependencyControl.config:write(true) - aegisub.log(3, "Done. You'll need to rescan your automation directory or restart aegisub for the changes to take effect.") -end - -local function change_config(modifier) -- i think i might be thinning out the soup a bit too much - DependencyControl.config:load() - local new_config = modifier(DependencyControl.config.c) - write_config(new_config) -end - -local function global_config() - change_config(get_config) -end - -local function extra_feeds() - change_config(get_feeds) -end - -depctrl:registerMacro("DependencyControl/Global Configuration", "Lets you change DependencyControl settings.", global_config) -depctrl:registerMacro("DependencyControl/Extra Feeds", "Lets you provide additional update feeds.", extra_feeds) diff --git a/macros/garret.dupe-and-comment.lua b/macros/garret.dupe-and-comment.lua deleted file mode 100644 index 16e2e97..0000000 --- a/macros/garret.dupe-and-comment.lua +++ /dev/null @@ -1,124 +0,0 @@ -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 diff --git a/macros/garret.karaoke2alpha.lua b/macros/garret.karaoke2alpha.lua deleted file mode 100644 index 51ff0c5..0000000 --- a/macros/garret.karaoke2alpha.lua +++ /dev/null @@ -1,70 +0,0 @@ -script_name = "K-Timing -> Alpha Timing" -script_description = "makes doing alpha timing significantly easier by getting rid of the part where you do alpha timing." -script_author = "garret" -script_version = "1.1.0" -script_namespace = "garret.karaoke2alpha" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -local util -if haveDepCtrl then - depctrl = DependencyControl { - --feed="TODO", - {"aegisub.util"} - } - util = depctrl:requireModules() -else - util = require 'aegisub.util' -end - -function get_visible(parsed_line, index) - local res = "" - for i=1,index do -- for every syl up to the current one - res = res..parsed_line[i].text -- add to the result - end - return res -end - -function get_invisible(parsed_line, index) - local res = "" - for i=index+1,#parsed_line do -- for every syl from the next one to the end - res = res..parsed_line[i].text -- add to result - end - return res -end - -function main(sub, sel) - for x=#sel,1,-1 do - local line=sub[sel[x]] - local parsed = aegisub.parse_karaoke_data(line) -- magic function that gets all the stuff about the karaoke - for i=1,#parsed do -- for every syl in the karaoke - visible = get_visible(parsed, i) - invisible = get_invisible(parsed, i) - if invisible ~= "" then -- if there's still invisible stuff left - text = visible.."{\\alpha&HFF&}"..invisible -- add an alpha tag and slap the invisible stuff on the end - else -- if it's all visible - text = visible -- don't need the alpha any more - end - local syl = parsed[i] - local new = util.copy(line) - new.text = text -- make a new line for this syl - -- set line start time - new.start_time = syl.start_time + line.start_time -- just the syl on its own returns the offset from the line - -- set line end time - if i ~= #parsed then -- if there's still invisible stuff left - new.end_time = syl.end_time + line.start_time -- end time is the syl's - else - new.end_time = line.end_time -- end time is the whole line's (i don't think this actually makes a difference but may as well) - end - sub.insert(sel[x] + i,new) -- add new lines (+1 line for first syl, +2 for 2nd syl, etc) - end - line.comment = true -- don't want to see the karaoke any more - sub[sel[x]]=line - end - aegisub.set_undo_point(script_name) -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.restyler.lua b/macros/garret.restyler.lua deleted file mode 100644 index 9430676..0000000 --- a/macros/garret.restyler.lua +++ /dev/null @@ -1,68 +0,0 @@ -script_name="Restyler" -script_description="become a fansubber with a click of a button" -script_author = "garret" -script_version = "2.1.1" -script_namespace = "garret.restyler" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -if haveDepCtrl then - depctrl = DependencyControl { - --feed="TODO", - } -end - -include("karaskel.lua") -include("cleantags.lua") - --- local config = simpleconf.get_config(aegisub.decode_path(config_dir.."/"..script_namespace..".conf"), {new_style = "Default"}) - --- TODO: detect pre-existing inline tags - -- probably need some kind of ass parsing, or a hack with match() - -function add_tags(txt, italic, align) -- everything except txt is boolean. nil = don't change, !nil = change to this value - ---[[not quite happy with this, it overwrites the alignment - ie line is "{\an4} blah blah" and style is an8, it just changes it to an8 -realisticly this _probably_ won't be a problem, but still would like to try and stop it at some point to be safe -italics is fine, it just does {\i1\i0}, which is jank and bad but works fine so i won't worry about it too much]] - if italic == true then - txt="{\\i1}"..txt - elseif italics == false then - txt="{\\i0}"..txt - end - if align ~= nil then - txt="{\\an"..align.."}"..txt - end - txt = cleantags(txt) - return txt -end - -function get_new(old, new) - local i = nil - if old ~= new then - i = old - end - return i -end - -function main(sub, sel) - local _, styles = karaskel.collect_head(sub, false) - local new_style_name = "Default" - local new_style = styles[new_style_name] - for h, i in ipairs(sel) do - -- TODO: automatically exclude styles (also configurable) - local line = sub[i] - local old_style = styles[line.style] -- reinventing the wheel a bit here, since karaskel can do this with preproc_line_size (line.styleref), but it also adds loads of other crap we don't care about for the same functionality in the end, so ¯\_(ツ)_/¯ - local italic = get_new(old_style.italic, new_style.italic) - local align = get_new(old_style.align, new_style.align) - line.style = new_style_name - line.text = add_tags(line.text, italic, align) - sub[i] = line - end - aegisub.set_undo_point(script_name) -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.select-comments.lua b/macros/garret.select-comments.lua deleted file mode 100644 index 6f0cf81..0000000 --- a/macros/garret.select-comments.lua +++ /dev/null @@ -1,33 +0,0 @@ -script_name = "Select comments" -script_description = "Select all commented lines" -script_author = "garret" -script_version = "1.1.0" -script_namespace = "garret.select-comments" --- faster than doing Subtitle -> Select Lines etc (at least in terms of button-presses) - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -if haveDepCtrl then - depctrl = DependencyControl { - --feed="TODO", - } -end --- this does not need depctrl at all lol --- just for consistency's sake really - -function main(sub) - sel = {} - for i=1,#sub do - line=sub[i] - if line.comment == true then - table.insert(sel, i) - end - end - aegisub.set_undo_point(script_name) - return sel -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.shenanigans.lua b/macros/garret.shenanigans.lua deleted file mode 100644 index bce22fc..0000000 --- a/macros/garret.shenanigans.lua +++ /dev/null @@ -1,81 +0,0 @@ -script_name = "Import Shenanigans" -script_description = "imports shenanigans" -script_author = "garret" -script_version = "0.1.1" -script_namespace = "garret.shenanigans" - -local SHENAN_PATTERN = "shenan ([^;]*)" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -local parser -if haveDepCtrl then - depctrl = DependencyControl({ - --feed="TODO", - { - { - "myaa.ASSParser", - version = "0.0.4", -- very sketch about this - url = "http://github.com/TypesettingTools/Myaamori-Aegisub-Scripts", - feed = "https://raw.githubusercontent.com/TypesettingTools/Myaamori-Aegisub-Scripts/master/DependencyControl.json", - optional = true, - }, - }, - }) - parser = depctrl:requireModules() -end - -local function main(sub) - local imports = {} - local i = 1 - - -- using a while/repeat until loop instead of a for here, so i can fuck around with the number - -- i do this to skip past shenanigans that've already been added without deleting them - - repeat - local line = sub[i] - if line.class == "dialogue" then - if line.effect == "import" then - local f = io.open(aegisub.decode_path(line.text), "r") - local imported_sub = parser.parse_file(f).events - f:close() - - for _, imported_line in ipairs(imported_sub) do - if imported_line.class == "dialogue" then - local name = imported_line.effect:match(SHENAN_PATTERN) - if name then - imports[name] = imports[name] or {} -- declare if not present - table.insert(imports[name], imported_line) - end - end - end - elseif line.effect ~= "" then - aegisub.log(5, i..": has effect: "..line.effect) - local name = line.effect:match(SHENAN_PATTERN) - local shenans = imports[name] - if shenans == nil then - - elseif shenans ~= "done" then - for idx, val in ipairs(shenans) do - sub.insert(i + idx, val) - end - sub.delete(sub, i) - i = i + #shenans - 1 - imports[name] = "done" - elseif shenans == "done" then - aegisub.log(5, "deleting "..line.text) - sub.delete(sub, i) - i = i - 1 -- the next line has now moved up 1, so we need to move up 1 as well - -- something about 2 hard problems - end - end - end - if i >= #sub then i = #sub end -- otherwise you can get out of range errors - i = i + 1 - until i == #sub + 1 -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/garret.sylsplitter.lua b/macros/garret.sylsplitter.lua deleted file mode 100644 index 615f730..0000000 --- a/macros/garret.sylsplitter.lua +++ /dev/null @@ -1,43 +0,0 @@ -script_name = "Syllable Splitter" -script_description = "splits romaji into syls of their original kana. for the lazy k-timer." -script_author = "garret" -script_version = "1.0.1" -script_namespace = "garret.sylsplitter" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -local re -if haveDepCtrl then - depctrl = DependencyControl({ - --feed="TODO", - { "aegisub.re" }, - }) - re = depctrl:requireModules() -else - re = require("aegisub.re") -end - -local function round(num, numDecimalPlaces) -- https://lua-users.org/wiki/SimpleRound - local mult = 10^(numDecimalPlaces or 0) - return math.floor(num * mult + 0.5) / mult -end - -local function add_tag(syl) - -- default syl duration = (line duration / line chars) * syl chars - local syl_dur = round(((line.end_time - line.start_time) / 10) / #line.text) - return "{\\k"..syl_dur * #syl .. "}" ..syl -end - -local function main(sub,sel) - local kana = re.compile("a|i|u|e|o|ya|yu|yo|ka|ki|ku|ke|ko|kya|kyu|kyo|sa|shi|su|se|so|sha|shu|sho|ta|chi|tsu|te|to|cha|chu|cho|na|ni|nu|ne|no|nya|nyu|nyo|ha|hi|fu|he|ho|hya|hyu|hyo|ma|mi|mu|me|mo|mya|myu|myo|ra|ri|ru|re|ro|rya|ryu|ryo|ga|gi|gu|ge|go|gya|gyu|gyo|za|ji|zu|ze|zo|ja|ju|jo|da|ji|zu|de|do|ja|ju|jo|ba|bi|bu|be|bo|bya|byu|byo|pa|pi|pu|pe|po|pya|pyu|pyo|wa|wo|n|-|[a-z]") -- all kana + all letters (for small っ) (probably dont need _all_ letters but whatever) - for i = 1, #sel do - line = sub[sel[i]] -- yes global, i know(ish) what im doing - line.text = kana:sub(line.text, add_tag) - sub[sel[i]] = line - end -end - -if haveDepCtrl then - depctrl:registerMacro("Split Syllables", script_description, main) -else - aegisub.register_macro("Split Syllables", script_description, main) -end diff --git a/macros/garret.timings_copier.lua b/macros/garret.timings_copier.lua deleted file mode 100644 index 8b79cc0..0000000 --- a/macros/garret.timings_copier.lua +++ /dev/null @@ -1,54 +0,0 @@ -script_name = "Timings copier" -script_description = "for copying song timings" -script_version = "1.0.0" -script_author = "garret" -script_namespace = "garret.timings_copier" - -local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") -if haveDepCtrl then - depctrl = DependencyControl {} -end - -local function get_blocks(sub, sel) - local src_style = sub[sel[1]].style - local src_len = 1 - for i = 2, #sel do - if sub[sel[i]].style == src_style then - src_len = src_len + 1 - else - break - end - end - local blocks = #sel / src_len - if blocks % 1 ~= 0 then - aegisub.log(0, "FATAL: Block lengths are not equal!\n") - aegisub.log(3, "HINT: Each \"block\" of lines must be the same length, e.g. you can't have less romaji than english, or vice versa. a block is a group of consecutive lines with the same style.") - aegisub.cancel() - else - return src_len, blocks - end -end - -local function copy(sub, sel, offset, blocks) - for index = 1, offset do - line = sub[sel[index]] - for mul = 1, blocks - 1 do - block_line = sub[sel[offset * mul + index]] - block_line.start_time = line.start_time - block_line.end_time = line.end_time - sub[sel[offset * mul + index]] = block_line - end - end -end - -local function main(sub, sel) - offset, blocks = get_blocks(sub, sel) - copy(sub, sel, offset, blocks) - aegisub.set_undo_point(script_name) -end - -if haveDepCtrl then - depctrl:registerMacro(main) -else - aegisub.register_macro(script_name, script_description, main) -end diff --git a/macros/light-purge.lua b/macros/light-purge.lua deleted file mode 100644 index b139266..0000000 --- a/macros/light-purge.lua +++ /dev/null @@ -1,46 +0,0 @@ -script_name = "TXT Cleanup" -script_description = "remove actors and/or linebreaks" -script_author = "garret" -script_version = "2.0.0" - -local function main(sub, conf) - for i = 1, #sub do - if sub[i].class == "dialogue" then - local line = sub[i] - if conf.purge_actors == true then - line.actor = "" - end - if conf.purge_linebreaks == true then - line.text = line.text:gsub(" *\\[Nn] *", " ") - end - sub[i] = line - end - end -end - -local function conf() - local conf = { - { - class = "checkbox", - name = "purge_actors", - x = 0, - y = 0, - width = 1, - height = 1, - label = "Remove Actors", - value = true, - }, - { - class = "checkbox", - name = "purge_linebreaks", - x = 0, - y = 1, - width = 1, - height = 1, - label = "Remove Linebreaks", - value = true, - }, - } - return conf -end -aegisub.register_filter(script_name, script_description, 1, main, conf) diff --git a/macros/pos2an.lua b/macros/pos2an.lua deleted file mode 100644 index 7b67b00..0000000 --- a/macros/pos2an.lua +++ /dev/null @@ -1,69 +0,0 @@ -script_name = "pos -> an" -script_description = "double click the video then snap to an \\an" -script_author = "garret" -script_version = "1" - - -local function escape_pattern(txt) - local magic_chars = "%^%$%(%)%%.%[%]%*%+%-%?" - return txt:gsub("(["..magic_chars.."])", "%%%1") -end - -local function main(sub, sel) - local vidx, vidy = aegisub.video_size() - local left = vidx * 0.25 - local right = vidx - (vidx * 0.25) - local top = vidy * 0.32 - local bottom = vidy - (vidx * 0.35) - -- todo: have these customisable in a gui in v2 - - if not vidx then - aegisub.log("open a video") - aegisub.cancel() - -- todo: might be nice to use script res for this - -- but realistically if youre using this, youve got a video open - end - for _, i in ipairs(sel) do - local line = sub[i] - local x - local y - local tag - local c = 0 - line.text = string.gsub(line.text, "\\an%d", "") - line.text = string.gsub(line.text, "{}", "") - for postag, posx, posy in string.gmatch(line.text, "{[^}]*(\\pos%(([^,]+), *([^)]+)%))[^}]*}") do - if c == 0 then - x = tonumber(posx) - y = tonumber(posy) - tag = escape_pattern(postag) - end - c = c + 1 - end - if c == 0 then goto continue end - -- aegi is luajit - - local s - - if y <= top then - s = "t" elseif - y >= bottom then s = "b" - else s = "c" end - - if x <= left then - s = s.."l" elseif - x >= right then s = s.."r" - else s = s.."c" end - - local AN_MAP = { - tl = 7, tc = 8, tr = 9, - cl = 4, cc = 5, cr = 6, - bl = 1, bc = 2, br = 3, - } - - line.text = string.gsub(line.text, tag, "\\an"..AN_MAP[s]) - sub[i] = line - ::continue:: - end -end - -aegisub.register_macro(script_name, script_description, main) diff --git a/macros/scenebleed.lua b/macros/scenebleed.lua deleted file mode 100644 index c0d3908..0000000 --- a/macros/scenebleed.lua +++ /dev/null @@ -1,35 +0,0 @@ -script_name="Scenebleed Detector" -script_description="marks possible scenebleeds with an effect" -script_author="garret" -script_version="2021-07-14" - -function main(sub, sel) - local thresh = aegisub.frame_from_ms(500) - local bleedstring = "bleed" - -- tried to make config file work, failed, so shit's hardcoded - - local keyframes = aegisub.keyframes() - local bleed_count = 0 - for j,i in ipairs(sel) do - line = sub[i] - local start_frame = aegisub.frame_from_ms(line.start_time) - local end_frame = aegisub.frame_from_ms(line.end_time) - for index, frame in ipairs(keyframes) do - if end_frame > frame and end_frame < frame + thresh or start_frame < frame and start_frame >= frame - thresh then - -- off the kf, but not by more than the threshold - if line.effect == "" then - line.effect = bleedstring - else - line.effect = line.effect.."; "..bleedstring - end - bleed_count = bleed_count + 1 - sub[i] = line - end - end - end - aegisub.log(bleed_count.." scenebleeds found.") - aegisub.set_undo_point(script_name) - return sel -end - -aegisub.register_macro(script_name, script_description, main) diff --git a/macros/songtimer.lua b/macros/songtimer.lua deleted file mode 100644 index 9ebafce..0000000 --- a/macros/songtimer.lua +++ /dev/null @@ -1,38 +0,0 @@ -script_name = "song timer" -script_description = "time songs while vibin" -script_author = "garret" -script_version = "1" - -local function main(sub, sel, act) - - local READY = "READY" - local START = "START" - local END = "END" - - local pos = aegisub.project_properties()['video_position'] - local ms = aegisub.ms_from_frame(pos) - local newline = sub[act] - newline.effect = READY - newline.text = "" - local nextline = newline - - local line = sub[act] - local endline = #sub - - if line.effect == READY then - line.start_time = ms - line.effect = START - sub[act] = line - elseif line.effect == START then - line.end_time = ms - line.effect = END - sub[act] = line - sub.append(nextline) - return {endline+1},endline+1 - else - sub.append(nextline) - return {endline+1},endline+1 - end -end - -aegisub.register_macro(script_name, script_description, main) diff --git a/pos2an.lua b/pos2an.lua new file mode 100644 index 0000000..7b67b00 --- /dev/null +++ b/pos2an.lua @@ -0,0 +1,69 @@ +script_name = "pos -> an" +script_description = "double click the video then snap to an \\an" +script_author = "garret" +script_version = "1" + + +local function escape_pattern(txt) + local magic_chars = "%^%$%(%)%%.%[%]%*%+%-%?" + return txt:gsub("(["..magic_chars.."])", "%%%1") +end + +local function main(sub, sel) + local vidx, vidy = aegisub.video_size() + local left = vidx * 0.25 + local right = vidx - (vidx * 0.25) + local top = vidy * 0.32 + local bottom = vidy - (vidx * 0.35) + -- todo: have these customisable in a gui in v2 + + if not vidx then + aegisub.log("open a video") + aegisub.cancel() + -- todo: might be nice to use script res for this + -- but realistically if youre using this, youve got a video open + end + for _, i in ipairs(sel) do + local line = sub[i] + local x + local y + local tag + local c = 0 + line.text = string.gsub(line.text, "\\an%d", "") + line.text = string.gsub(line.text, "{}", "") + for postag, posx, posy in string.gmatch(line.text, "{[^}]*(\\pos%(([^,]+), *([^)]+)%))[^}]*}") do + if c == 0 then + x = tonumber(posx) + y = tonumber(posy) + tag = escape_pattern(postag) + end + c = c + 1 + end + if c == 0 then goto continue end + -- aegi is luajit + + local s + + if y <= top then + s = "t" elseif + y >= bottom then s = "b" + else s = "c" end + + if x <= left then + s = s.."l" elseif + x >= right then s = s.."r" + else s = s.."c" end + + local AN_MAP = { + tl = 7, tc = 8, tr = 9, + cl = 4, cc = 5, cr = 6, + bl = 1, bc = 2, br = 3, + } + + line.text = string.gsub(line.text, tag, "\\an"..AN_MAP[s]) + sub[i] = line + ::continue:: + end +end + +aegisub.register_macro(script_name, script_description, main) diff --git a/restyler.lua b/restyler.lua new file mode 100644 index 0000000..9430676 --- /dev/null +++ b/restyler.lua @@ -0,0 +1,68 @@ +script_name="Restyler" +script_description="become a fansubber with a click of a button" +script_author = "garret" +script_version = "2.1.1" +script_namespace = "garret.restyler" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +if haveDepCtrl then + depctrl = DependencyControl { + --feed="TODO", + } +end + +include("karaskel.lua") +include("cleantags.lua") + +-- local config = simpleconf.get_config(aegisub.decode_path(config_dir.."/"..script_namespace..".conf"), {new_style = "Default"}) + +-- TODO: detect pre-existing inline tags + -- probably need some kind of ass parsing, or a hack with match() + +function add_tags(txt, italic, align) -- everything except txt is boolean. nil = don't change, !nil = change to this value + +--[[not quite happy with this, it overwrites the alignment - ie line is "{\an4} blah blah" and style is an8, it just changes it to an8 +realisticly this _probably_ won't be a problem, but still would like to try and stop it at some point to be safe +italics is fine, it just does {\i1\i0}, which is jank and bad but works fine so i won't worry about it too much]] + if italic == true then + txt="{\\i1}"..txt + elseif italics == false then + txt="{\\i0}"..txt + end + if align ~= nil then + txt="{\\an"..align.."}"..txt + end + txt = cleantags(txt) + return txt +end + +function get_new(old, new) + local i = nil + if old ~= new then + i = old + end + return i +end + +function main(sub, sel) + local _, styles = karaskel.collect_head(sub, false) + local new_style_name = "Default" + local new_style = styles[new_style_name] + for h, i in ipairs(sel) do + -- TODO: automatically exclude styles (also configurable) + local line = sub[i] + local old_style = styles[line.style] -- reinventing the wheel a bit here, since karaskel can do this with preproc_line_size (line.styleref), but it also adds loads of other crap we don't care about for the same functionality in the end, so ¯\_(ツ)_/¯ + local italic = get_new(old_style.italic, new_style.italic) + local align = get_new(old_style.align, new_style.align) + line.style = new_style_name + line.text = add_tags(line.text, italic, align) + sub[i] = line + end + aegisub.set_undo_point(script_name) +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/scenebleed.lua b/scenebleed.lua new file mode 100644 index 0000000..c0d3908 --- /dev/null +++ b/scenebleed.lua @@ -0,0 +1,35 @@ +script_name="Scenebleed Detector" +script_description="marks possible scenebleeds with an effect" +script_author="garret" +script_version="2021-07-14" + +function main(sub, sel) + local thresh = aegisub.frame_from_ms(500) + local bleedstring = "bleed" + -- tried to make config file work, failed, so shit's hardcoded + + local keyframes = aegisub.keyframes() + local bleed_count = 0 + for j,i in ipairs(sel) do + line = sub[i] + local start_frame = aegisub.frame_from_ms(line.start_time) + local end_frame = aegisub.frame_from_ms(line.end_time) + for index, frame in ipairs(keyframes) do + if end_frame > frame and end_frame < frame + thresh or start_frame < frame and start_frame >= frame - thresh then + -- off the kf, but not by more than the threshold + if line.effect == "" then + line.effect = bleedstring + else + line.effect = line.effect.."; "..bleedstring + end + bleed_count = bleed_count + 1 + sub[i] = line + end + end + end + aegisub.log(bleed_count.." scenebleeds found.") + aegisub.set_undo_point(script_name) + return sel +end + +aegisub.register_macro(script_name, script_description, main) diff --git a/select-comments.lua b/select-comments.lua new file mode 100644 index 0000000..6f0cf81 --- /dev/null +++ b/select-comments.lua @@ -0,0 +1,33 @@ +script_name = "Select comments" +script_description = "Select all commented lines" +script_author = "garret" +script_version = "1.1.0" +script_namespace = "garret.select-comments" +-- faster than doing Subtitle -> Select Lines etc (at least in terms of button-presses) + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +if haveDepCtrl then + depctrl = DependencyControl { + --feed="TODO", + } +end +-- this does not need depctrl at all lol +-- just for consistency's sake really + +function main(sub) + sel = {} + for i=1,#sub do + line=sub[i] + if line.comment == true then + table.insert(sel, i) + end + end + aegisub.set_undo_point(script_name) + return sel +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/shenanigans.lua b/shenanigans.lua new file mode 100644 index 0000000..bce22fc --- /dev/null +++ b/shenanigans.lua @@ -0,0 +1,81 @@ +script_name = "Import Shenanigans" +script_description = "imports shenanigans" +script_author = "garret" +script_version = "0.1.1" +script_namespace = "garret.shenanigans" + +local SHENAN_PATTERN = "shenan ([^;]*)" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +local parser +if haveDepCtrl then + depctrl = DependencyControl({ + --feed="TODO", + { + { + "myaa.ASSParser", + version = "0.0.4", -- very sketch about this + url = "http://github.com/TypesettingTools/Myaamori-Aegisub-Scripts", + feed = "https://raw.githubusercontent.com/TypesettingTools/Myaamori-Aegisub-Scripts/master/DependencyControl.json", + optional = true, + }, + }, + }) + parser = depctrl:requireModules() +end + +local function main(sub) + local imports = {} + local i = 1 + + -- using a while/repeat until loop instead of a for here, so i can fuck around with the number + -- i do this to skip past shenanigans that've already been added without deleting them + + repeat + local line = sub[i] + if line.class == "dialogue" then + if line.effect == "import" then + local f = io.open(aegisub.decode_path(line.text), "r") + local imported_sub = parser.parse_file(f).events + f:close() + + for _, imported_line in ipairs(imported_sub) do + if imported_line.class == "dialogue" then + local name = imported_line.effect:match(SHENAN_PATTERN) + if name then + imports[name] = imports[name] or {} -- declare if not present + table.insert(imports[name], imported_line) + end + end + end + elseif line.effect ~= "" then + aegisub.log(5, i..": has effect: "..line.effect) + local name = line.effect:match(SHENAN_PATTERN) + local shenans = imports[name] + if shenans == nil then + + elseif shenans ~= "done" then + for idx, val in ipairs(shenans) do + sub.insert(i + idx, val) + end + sub.delete(sub, i) + i = i + #shenans - 1 + imports[name] = "done" + elseif shenans == "done" then + aegisub.log(5, "deleting "..line.text) + sub.delete(sub, i) + i = i - 1 -- the next line has now moved up 1, so we need to move up 1 as well + -- something about 2 hard problems + end + end + end + if i >= #sub then i = #sub end -- otherwise you can get out of range errors + i = i + 1 + until i == #sub + 1 +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end diff --git a/songtimer.lua b/songtimer.lua new file mode 100644 index 0000000..9ebafce --- /dev/null +++ b/songtimer.lua @@ -0,0 +1,38 @@ +script_name = "song timer" +script_description = "time songs while vibin" +script_author = "garret" +script_version = "1" + +local function main(sub, sel, act) + + local READY = "READY" + local START = "START" + local END = "END" + + local pos = aegisub.project_properties()['video_position'] + local ms = aegisub.ms_from_frame(pos) + local newline = sub[act] + newline.effect = READY + newline.text = "" + local nextline = newline + + local line = sub[act] + local endline = #sub + + if line.effect == READY then + line.start_time = ms + line.effect = START + sub[act] = line + elseif line.effect == START then + line.end_time = ms + line.effect = END + sub[act] = line + sub.append(nextline) + return {endline+1},endline+1 + else + sub.append(nextline) + return {endline+1},endline+1 + end +end + +aegisub.register_macro(script_name, script_description, main) diff --git a/sylsplitter.lua b/sylsplitter.lua new file mode 100644 index 0000000..615f730 --- /dev/null +++ b/sylsplitter.lua @@ -0,0 +1,43 @@ +script_name = "Syllable Splitter" +script_description = "splits romaji into syls of their original kana. for the lazy k-timer." +script_author = "garret" +script_version = "1.0.1" +script_namespace = "garret.sylsplitter" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +local re +if haveDepCtrl then + depctrl = DependencyControl({ + --feed="TODO", + { "aegisub.re" }, + }) + re = depctrl:requireModules() +else + re = require("aegisub.re") +end + +local function round(num, numDecimalPlaces) -- https://lua-users.org/wiki/SimpleRound + local mult = 10^(numDecimalPlaces or 0) + return math.floor(num * mult + 0.5) / mult +end + +local function add_tag(syl) + -- default syl duration = (line duration / line chars) * syl chars + local syl_dur = round(((line.end_time - line.start_time) / 10) / #line.text) + return "{\\k"..syl_dur * #syl .. "}" ..syl +end + +local function main(sub,sel) + local kana = re.compile("a|i|u|e|o|ya|yu|yo|ka|ki|ku|ke|ko|kya|kyu|kyo|sa|shi|su|se|so|sha|shu|sho|ta|chi|tsu|te|to|cha|chu|cho|na|ni|nu|ne|no|nya|nyu|nyo|ha|hi|fu|he|ho|hya|hyu|hyo|ma|mi|mu|me|mo|mya|myu|myo|ra|ri|ru|re|ro|rya|ryu|ryo|ga|gi|gu|ge|go|gya|gyu|gyo|za|ji|zu|ze|zo|ja|ju|jo|da|ji|zu|de|do|ja|ju|jo|ba|bi|bu|be|bo|bya|byu|byo|pa|pi|pu|pe|po|pya|pyu|pyo|wa|wo|n|-|[a-z]") -- all kana + all letters (for small っ) (probably dont need _all_ letters but whatever) + for i = 1, #sel do + line = sub[sel[i]] -- yes global, i know(ish) what im doing + line.text = kana:sub(line.text, add_tag) + sub[sel[i]] = line + end +end + +if haveDepCtrl then + depctrl:registerMacro("Split Syllables", script_description, main) +else + aegisub.register_macro("Split Syllables", script_description, main) +end diff --git a/timings_copier.lua b/timings_copier.lua new file mode 100644 index 0000000..8b79cc0 --- /dev/null +++ b/timings_copier.lua @@ -0,0 +1,54 @@ +script_name = "Timings copier" +script_description = "for copying song timings" +script_version = "1.0.0" +script_author = "garret" +script_namespace = "garret.timings_copier" + +local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl") +if haveDepCtrl then + depctrl = DependencyControl {} +end + +local function get_blocks(sub, sel) + local src_style = sub[sel[1]].style + local src_len = 1 + for i = 2, #sel do + if sub[sel[i]].style == src_style then + src_len = src_len + 1 + else + break + end + end + local blocks = #sel / src_len + if blocks % 1 ~= 0 then + aegisub.log(0, "FATAL: Block lengths are not equal!\n") + aegisub.log(3, "HINT: Each \"block\" of lines must be the same length, e.g. you can't have less romaji than english, or vice versa. a block is a group of consecutive lines with the same style.") + aegisub.cancel() + else + return src_len, blocks + end +end + +local function copy(sub, sel, offset, blocks) + for index = 1, offset do + line = sub[sel[index]] + for mul = 1, blocks - 1 do + block_line = sub[sel[offset * mul + index]] + block_line.start_time = line.start_time + block_line.end_time = line.end_time + sub[sel[offset * mul + index]] = block_line + end + end +end + +local function main(sub, sel) + offset, blocks = get_blocks(sub, sel) + copy(sub, sel, offset, blocks) + aegisub.set_undo_point(script_name) +end + +if haveDepCtrl then + depctrl:registerMacro(main) +else + aegisub.register_macro(script_name, script_description, main) +end -- cgit v1.2.3-70-g09d2