Skip to content

Instantly share code, notes, and snippets.

@touilleMan
Last active January 9, 2020 11:45
Show Gist options
  • Save touilleMan/a1dd730570d06b80db3d to your computer and use it in GitHub Desktop.
Save touilleMan/a1dd730570d06b80db3d to your computer and use it in GitHub Desktop.
Aegisub script to do multiple replacements a once on the sub
--[[
multiReplace is (c) 2015 by Emmanuel Leblond <[email protected]>.
It is licensed to you under the terms of the WTFPLv2 (see below).
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <[email protected]>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
README:
Multiple Replace script, just provide the `replaces` field with something like
```
pattern1
value1
pattern2
value2
```
i.e. a pattern to search followed by it replacement, empty newlines and
patterns not followed by a replacement are ignored.
]]
-- Config, put here what you don't want to type each time
DEFAULT_REPLACES=[[
]]
DEFAULT_LIGNE_SEPARATOR='\\N'
DEFAULT_LIGNE_TARGET=1
-- DEFAULT_LINESELECT="Apply to selected lines"
DEFAULT_LINESELECT="Apply to all lines"
-- End of config, don't touch after that (unless you know what you're doing...)
-- Define some properties about the script
script_name="Multi-Replace"
script_description="Replace multiple patterns at once"
script_author="Emmanuel Leblond"
script_version="1.0"
-- No split in lua... seriously ??? O_o
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
buttons={"Start","Cancel"}
dialog_config={
{
class="dropdown",name="lineselect",
x=0,y=0,width=1,height=1,
items={"Apply to selected lines","Apply to all lines"},
value=DEFAULT_LINESELECT
},
{
class="label",
x=0,y=1,width=1,height=1,
label="\\line separator:"
},
{
class="edit",name="lseparator",
x=1,y=1,width=1,height=1,
value=DEFAULT_LIGNE_SEPARATOR
},
{
class="label",
x=0,y=2,width=1,height=1,
label="\\line target:"
},
{
class="intedit",name="ltarget",
x=1,y=2,width=1,height=1,
value=DEFAULT_LIGNE_TARGET
},
{
class="label",
x=0,y=3,width=2,height=1,
label="\\pattern=replace (one per line)"
},
{
class="textbox",name="replaces",
x=0,y=4,width=2,height=4,
value=DEFAULT_REPLACES
},
}
function process_line(line, separator, target, replaces)
local splitted = {}
if separator == '' then
-- no separator, parse the entire line
table.insert(splitted, line.text)
target = 1
else
splitted = split(line.text, separator)
end
local texts = {}
for i, sub_text in pairs(splitted) do
if target == i then
for _, data in ipairs(replaces) do
pattern = data[1]
replace = data[2]
sub_text = sub_text:gsub(pattern, replace)
end
end
table.insert(texts, sub_text)
end
if #texts ~= 0 then
line.text = table.concat(texts, separator)
end
return line
end
function parse_replaces(raw_replaces)
local replaces = {}
local current_pattern = nil
for i, raw_expr in pairs(split(raw_replaces, "\n")) do
if raw_expr ~= nil and raw_expr ~= '' then
-- current line contains something
if not current_pattern then
-- this line is the pattern to search
current_pattern = raw_expr
else
-- this line is the replacement
table.insert(replaces, {current_pattern, raw_expr})
current_pattern = nil
end
else
-- current line is just a newline,
current_pattern = nil
end
end
return replaces
end
--This is the main processing function that modifies the subtitles
function macro_function(sub, sel, act)
local pressed, results = aegisub.dialog.display(dialog_config,buttons)
if pressed=="Cancel" then
aegisub.cancel()
end
local replaces = parse_replaces(results['replaces'])
local lseparator = results['lseparator']
local ltarget = results['ltarget']
if results['lineselect'] == "Apply to selected lines" then
for si,li in ipairs(sel) do
sub[li] = process_line(sub[li], lseparator, ltarget, replaces)
aegisub.progress.set(si*100/#sel)
end
else
for li=1,#sub do
if sub[li].class == "dialogue" then
sub[li] = process_line(sub[li], lseparator, ltarget, replaces)
aegisub.progress.set(li*100/#sub)
end
end
end
return sel -- Preserve user selection
end
--This optional function lets you prevent the user from running the macro on bad input
function macro_validation(sub, sel, act)
--Check if the user has selected valid lines
--If so, return true. Otherwise, return false
return true
end
--This is what puts your automation in Aegisub's automation list
aegisub.register_macro(script_name,script_description,macro_function,macro_validation)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment