diff --git a/aegisub/automation/include/aegisub/clipboard.lua b/aegisub/automation/include/aegisub/clipboard.lua new file mode 100644 index 000000000..00b156ce3 --- /dev/null +++ b/aegisub/automation/include/aegisub/clipboard.lua @@ -0,0 +1,15 @@ +-- Copyright (c) 2012, Thomas Goyne +-- +-- Permission to use, copy, modify, and distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +-- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +-- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +-- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +return aegisub.__init_clipboard() diff --git a/aegisub/automation/include/aegisub/re.lua b/aegisub/automation/include/aegisub/re.lua new file mode 100644 index 000000000..32413ed9c --- /dev/null +++ b/aegisub/automation/include/aegisub/re.lua @@ -0,0 +1,314 @@ +local regex = aegisub.__init_regex() +local select_first +select_first = function(n, a, ...) + if n == 0 then + return + end + return a, select_first(n - 1, ...) +end +local unpack_args +unpack_args = function(...) + local userdata_start = nil + for i = 1, select('#', ...) do + local v = select(i, ...) + if type(v) == 'userdata' then + userdata_start = i + break + end + end + if not (userdata_start) then + return 0, ... + end + local flags = regex.process_flags(select(userdata_start, ...)) + if type(flags) == 'string' then + error(flags, 3) + end + return flags, select_first(userdata_start - 1, ...) +end +local check_arg +check_arg = function(arg, expected_type, argn, func_name, level) + if type(arg) ~= expected_type then + return error("Argument " .. tostring(argn) .. " to " .. tostring(func_name) .. " should be a '" .. tostring(expected_type) .. "', is '" .. tostring(type(arg)) .. "' (" .. tostring(arg) .. ")", level + 1) + end +end +local replace_match +replace_match = function(match, func, str, last, acc) + if last < match.last then + acc[#acc + 1] = str:sub(last, match.first - 1) + end + local repl = func(match.str, match.first, match.last) + if type(repl) == 'string' then + acc[#acc + 1] = repl + else + acc[#acc + 1] = match.str + end + return match.first, match.last + 1 +end +local do_single_replace_fun +do_single_replace_fun = function(re, func, str, acc, pos) + local matches = re:match(str, pos) + if not (matches) then + return pos + end + local start + if #matches == 1 then + start = 1 + else + start = 2 + end + local last = pos + local first + for i = start, #matches do + first, last = replace_match(matches[i], func, str, last, acc) + end + if first == last then + acc[#acc + 1] = str:sub(last, last) + last = last + 1 + end + return last, matches[1].first <= str:len() +end +local do_replace_fun +do_replace_fun = function(re, func, str, max) + local acc = { } + local pos = 1 + local i + for i = 1, max do + local more + pos, more = do_single_replace_fun(re, func, str, acc, pos) + if not (more) then + max = i + break + end + end + return table.concat(acc, '') .. str:sub(pos) +end +local RegEx +do + local start + local _parent_0 = nil + local _base_0 = { + _check_self = function(self) + if not (self.__class == RegEx) then + return error('re method called with invalid self. You probably used . when : is needed.', 3) + end + end, + gsplit = function(self, str, skip_empty, max_split) + self:_check_self() + check_arg(str, 'string', 2, 'gsplit', self._level) + if not max_split or max_split <= 0 then + max_split = str:len() + end + start = 1 + local prev = 1 + local do_split + do_split = function() + if not str or str:len() == 0 then + return + end + local first, last + if max_split > 0 then + first, last = regex.search(self._regex, str, start) + end + if not first or first > str:len() then + local ret = str:sub(prev, str:len()) + str = nil + return ret + end + local ret = str:sub(prev, first - 1) + prev = last + 1 + start = 1 + (function() + if start >= last then + return start + else + return last + end + end)() + if skip_empty and ret:len() == 0 then + return do_split() + else + max_split = max_split - 1 + return ret + end + end + return do_split + end, + split = function(self, str, skip_empty, max_split) + self:_check_self() + check_arg(str, 'string', 2, 'split', self._level) + return (function() + local _accum_0 = { } + local _len_0 = 1 + for v in self:gsplit(str, skip_empty, max_split) do + _accum_0[_len_0] = v + _len_0 = _len_0 + 1 + end + return _accum_0 + end)() + end, + gfind = function(self, str) + self:_check_self() + check_arg(str, 'string', 2, 'gfind', self._level) + start = 1 + return function() + local first, last = regex.search(self._regex, str, start) + if not (first) then + return + end + if last >= start then + start = last + 1 + else + start = start + 1 + end + return str:sub(first, last), first, last + end + end, + find = function(self, str) + self:_check_self() + check_arg(str, 'string', 2, 'find', self._level) + local ret = (function() + local _accum_0 = { } + local _len_0 = 1 + for s, f, l in self:gfind(str) do + _accum_0[_len_0] = { + str = s, + first = f, + last = l + } + _len_0 = _len_0 + 1 + end + return _accum_0 + end)() + return next(ret) and ret + end, + sub = function(self, str, repl, max_count) + self:_check_self() + check_arg(str, 'string', 2, 'sub', self._level) + if max_count ~= nil then + check_arg(max_count, 'number', 4, 'sub', self._level) + end + if not max_count or max_count == 0 then + max_count = str:len() + 1 + end + if type(repl) == 'function' then + return do_replace_fun(self, repl, str, max_count) + elseif type(repl) == 'string' then + return regex.replace(self._regex, repl, str, max_count) + else + return error("Argument 2 to sub should be a string or function, is '" .. tostring(type(repl)) .. "' (" .. tostring(repl) .. ")", self._level) + end + end, + gmatch = function(self, str, start) + self:_check_self() + check_arg(str, 'string', 2, 'gmatch', self._level) + if start then + start = start - 1 + else + start = 0 + end + local match = regex.match(self._regex, str, start) + local i = 1 + return function() + if not (match) then + return + end + local first, last = regex.get_match(match, i) + if not (first) then + return + end + i = i + 1 + return { + str = str:sub(first + start, last + start), + first = first + start, + last = last + start + } + end + end, + match = function(self, str, start) + self:_check_self() + check_arg(str, 'string', 2, 'match', self._level) + local ret = (function() + local _accum_0 = { } + local _len_0 = 1 + for v in self:gmatch(str, start) do + _accum_0[_len_0] = v + _len_0 = _len_0 + 1 + end + return _accum_0 + end)() + if next(ret) == nil then + return nil + end + return ret + end + } + _base_0.__index = _base_0 + if _parent_0 then + setmetatable(_base_0, _parent_0.__base) + end + local _class_0 = setmetatable({ + __init = function(self, _regex, _level) + self._regex, self._level = _regex, _level + end, + __base = _base_0, + __name = "RegEx", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil and _parent_0 then + return _parent_0[name] + else + return val + end + end, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + local self = _class_0 + start = 1 + if _parent_0 and _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + RegEx = _class_0 +end +local real_compile +real_compile = function(pattern, level, flags, stored_level) + if pattern == '' then + error('Regular expression must not be empty', level + 1) + end + local re = regex.compile(pattern, flags) + if type(re) == 'string' then + error(regex, level + 1) + end + return RegEx(re, stored_level or level + 1) +end +local invoke +invoke = function(str, pattern, fn, flags, ...) + local compiled_regex = real_compile(pattern, 3, flags) + return compiled_regex[fn](compiled_regex, str, ...) +end +local gen_wrapper +gen_wrapper = function(impl_name) + return function(str, pattern, ...) + check_arg(str, 'string', 1, impl_name, 2) + check_arg(pattern, 'string', 2, impl_name, 2) + return invoke(str, pattern, impl_name, unpack_args(...)) + end +end +local re = regex.init_flags(re) +re.compile = function(pattern, ...) + check_arg(pattern, 'string', 1, 'compile', 2) + return real_compile(pattern, 2, regex.process_flags(...), 2) +end +re.split = gen_wrapper('split') +re.gsplit = gen_wrapper('gsplit') +re.find = gen_wrapper('find') +re.gfind = gen_wrapper('gfind') +re.match = gen_wrapper('match') +re.gmatch = gen_wrapper('gmatch') +re.sub = gen_wrapper('sub') +return re diff --git a/aegisub/automation/include/re.moon b/aegisub/automation/include/aegisub/re.moon similarity index 100% rename from aegisub/automation/include/re.moon rename to aegisub/automation/include/aegisub/re.moon diff --git a/aegisub/automation/include/clipboard.lua b/aegisub/automation/include/clipboard.lua index 00b156ce3..5033add1b 100644 --- a/aegisub/automation/include/clipboard.lua +++ b/aegisub/automation/include/clipboard.lua @@ -12,4 +12,5 @@ -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -return aegisub.__init_clipboard() +_G.clipboard = aegisub.__init_clipboard() +return _G.clipboard diff --git a/aegisub/automation/include/re.lua b/aegisub/automation/include/re.lua index 32413ed9c..64dbbd645 100644 --- a/aegisub/automation/include/re.lua +++ b/aegisub/automation/include/re.lua @@ -1,314 +1,16 @@ -local regex = aegisub.__init_regex() -local select_first -select_first = function(n, a, ...) - if n == 0 then - return - end - return a, select_first(n - 1, ...) -end -local unpack_args -unpack_args = function(...) - local userdata_start = nil - for i = 1, select('#', ...) do - local v = select(i, ...) - if type(v) == 'userdata' then - userdata_start = i - break - end - end - if not (userdata_start) then - return 0, ... - end - local flags = regex.process_flags(select(userdata_start, ...)) - if type(flags) == 'string' then - error(flags, 3) - end - return flags, select_first(userdata_start - 1, ...) -end -local check_arg -check_arg = function(arg, expected_type, argn, func_name, level) - if type(arg) ~= expected_type then - return error("Argument " .. tostring(argn) .. " to " .. tostring(func_name) .. " should be a '" .. tostring(expected_type) .. "', is '" .. tostring(type(arg)) .. "' (" .. tostring(arg) .. ")", level + 1) - end -end -local replace_match -replace_match = function(match, func, str, last, acc) - if last < match.last then - acc[#acc + 1] = str:sub(last, match.first - 1) - end - local repl = func(match.str, match.first, match.last) - if type(repl) == 'string' then - acc[#acc + 1] = repl - else - acc[#acc + 1] = match.str - end - return match.first, match.last + 1 -end -local do_single_replace_fun -do_single_replace_fun = function(re, func, str, acc, pos) - local matches = re:match(str, pos) - if not (matches) then - return pos - end - local start - if #matches == 1 then - start = 1 - else - start = 2 - end - local last = pos - local first - for i = start, #matches do - first, last = replace_match(matches[i], func, str, last, acc) - end - if first == last then - acc[#acc + 1] = str:sub(last, last) - last = last + 1 - end - return last, matches[1].first <= str:len() -end -local do_replace_fun -do_replace_fun = function(re, func, str, max) - local acc = { } - local pos = 1 - local i - for i = 1, max do - local more - pos, more = do_single_replace_fun(re, func, str, acc, pos) - if not (more) then - max = i - break - end - end - return table.concat(acc, '') .. str:sub(pos) -end -local RegEx -do - local start - local _parent_0 = nil - local _base_0 = { - _check_self = function(self) - if not (self.__class == RegEx) then - return error('re method called with invalid self. You probably used . when : is needed.', 3) - end - end, - gsplit = function(self, str, skip_empty, max_split) - self:_check_self() - check_arg(str, 'string', 2, 'gsplit', self._level) - if not max_split or max_split <= 0 then - max_split = str:len() - end - start = 1 - local prev = 1 - local do_split - do_split = function() - if not str or str:len() == 0 then - return - end - local first, last - if max_split > 0 then - first, last = regex.search(self._regex, str, start) - end - if not first or first > str:len() then - local ret = str:sub(prev, str:len()) - str = nil - return ret - end - local ret = str:sub(prev, first - 1) - prev = last + 1 - start = 1 + (function() - if start >= last then - return start - else - return last - end - end)() - if skip_empty and ret:len() == 0 then - return do_split() - else - max_split = max_split - 1 - return ret - end - end - return do_split - end, - split = function(self, str, skip_empty, max_split) - self:_check_self() - check_arg(str, 'string', 2, 'split', self._level) - return (function() - local _accum_0 = { } - local _len_0 = 1 - for v in self:gsplit(str, skip_empty, max_split) do - _accum_0[_len_0] = v - _len_0 = _len_0 + 1 - end - return _accum_0 - end)() - end, - gfind = function(self, str) - self:_check_self() - check_arg(str, 'string', 2, 'gfind', self._level) - start = 1 - return function() - local first, last = regex.search(self._regex, str, start) - if not (first) then - return - end - if last >= start then - start = last + 1 - else - start = start + 1 - end - return str:sub(first, last), first, last - end - end, - find = function(self, str) - self:_check_self() - check_arg(str, 'string', 2, 'find', self._level) - local ret = (function() - local _accum_0 = { } - local _len_0 = 1 - for s, f, l in self:gfind(str) do - _accum_0[_len_0] = { - str = s, - first = f, - last = l - } - _len_0 = _len_0 + 1 - end - return _accum_0 - end)() - return next(ret) and ret - end, - sub = function(self, str, repl, max_count) - self:_check_self() - check_arg(str, 'string', 2, 'sub', self._level) - if max_count ~= nil then - check_arg(max_count, 'number', 4, 'sub', self._level) - end - if not max_count or max_count == 0 then - max_count = str:len() + 1 - end - if type(repl) == 'function' then - return do_replace_fun(self, repl, str, max_count) - elseif type(repl) == 'string' then - return regex.replace(self._regex, repl, str, max_count) - else - return error("Argument 2 to sub should be a string or function, is '" .. tostring(type(repl)) .. "' (" .. tostring(repl) .. ")", self._level) - end - end, - gmatch = function(self, str, start) - self:_check_self() - check_arg(str, 'string', 2, 'gmatch', self._level) - if start then - start = start - 1 - else - start = 0 - end - local match = regex.match(self._regex, str, start) - local i = 1 - return function() - if not (match) then - return - end - local first, last = regex.get_match(match, i) - if not (first) then - return - end - i = i + 1 - return { - str = str:sub(first + start, last + start), - first = first + start, - last = last + start - } - end - end, - match = function(self, str, start) - self:_check_self() - check_arg(str, 'string', 2, 'match', self._level) - local ret = (function() - local _accum_0 = { } - local _len_0 = 1 - for v in self:gmatch(str, start) do - _accum_0[_len_0] = v - _len_0 = _len_0 + 1 - end - return _accum_0 - end)() - if next(ret) == nil then - return nil - end - return ret - end - } - _base_0.__index = _base_0 - if _parent_0 then - setmetatable(_base_0, _parent_0.__base) - end - local _class_0 = setmetatable({ - __init = function(self, _regex, _level) - self._regex, self._level = _regex, _level - end, - __base = _base_0, - __name = "RegEx", - __parent = _parent_0 - }, { - __index = function(cls, name) - local val = rawget(_base_0, name) - if val == nil and _parent_0 then - return _parent_0[name] - else - return val - end - end, - __call = function(cls, ...) - local _self_0 = setmetatable({}, _base_0) - cls.__init(_self_0, ...) - return _self_0 - end - }) - _base_0.__class = _class_0 - local self = _class_0 - start = 1 - if _parent_0 and _parent_0.__inherited then - _parent_0.__inherited(_parent_0, _class_0) - end - RegEx = _class_0 -end -local real_compile -real_compile = function(pattern, level, flags, stored_level) - if pattern == '' then - error('Regular expression must not be empty', level + 1) - end - local re = regex.compile(pattern, flags) - if type(re) == 'string' then - error(regex, level + 1) - end - return RegEx(re, stored_level or level + 1) -end -local invoke -invoke = function(str, pattern, fn, flags, ...) - local compiled_regex = real_compile(pattern, 3, flags) - return compiled_regex[fn](compiled_regex, str, ...) -end -local gen_wrapper -gen_wrapper = function(impl_name) - return function(str, pattern, ...) - check_arg(str, 'string', 1, impl_name, 2) - check_arg(pattern, 'string', 2, impl_name, 2) - return invoke(str, pattern, impl_name, unpack_args(...)) - end -end -local re = regex.init_flags(re) -re.compile = function(pattern, ...) - check_arg(pattern, 'string', 1, 'compile', 2) - return real_compile(pattern, 2, regex.process_flags(...), 2) -end -re.split = gen_wrapper('split') -re.gsplit = gen_wrapper('gsplit') -re.find = gen_wrapper('find') -re.gfind = gen_wrapper('gfind') -re.match = gen_wrapper('match') -re.gmatch = gen_wrapper('gmatch') -re.sub = gen_wrapper('sub') -return re +-- Copyright (c) 2013, Thomas Goyne +-- +-- Permission to use, copy, modify, and distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +-- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +-- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +-- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +_G.re = require 'aegisub.re' +return _G.re