<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FErutuon%2FUnicode</id>
	<title>Module:Sandbox/Erutuon/Unicode - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FErutuon%2FUnicode"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Erutuon/Unicode&amp;action=history"/>
	<updated>2026-04-10T00:51:15Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Sandbox/Erutuon/Unicode&amp;diff=145390&amp;oldid=prev</id>
		<title>imported&gt;Erutuon: Module:Table → Module:TableTools</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Erutuon/Unicode&amp;diff=145390&amp;oldid=prev"/>
		<updated>2019-02-28T01:35:22Z</updated>

		<summary type="html">&lt;p&gt;&lt;a href=&quot;/index.php?title=Module:Table&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Module:Table (page does not exist)&quot;&gt;Module:Table&lt;/a&gt; → &lt;a href=&quot;/research/Module:TableTools&quot; title=&quot;Module:TableTools&quot;&gt;Module:TableTools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
local Unicode_data = require &amp;quot;Module:Unicode data/sandbox&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local function errorf(level, ...)&lt;br /&gt;
	if type(level) == &amp;quot;number&amp;quot; then&lt;br /&gt;
		return error(string.format(...), level + 1)&lt;br /&gt;
	else -- level is actually the format string.&lt;br /&gt;
		return error(string.format(level, ...), 2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mw.logf(...)&lt;br /&gt;
	return mw.log(string.format(...))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local output_mt = {}&lt;br /&gt;
function output_mt:insert(str)&lt;br /&gt;
	self.n = self.n + 1&lt;br /&gt;
	self[self.n] = str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- also in [[Module:Unicode data/documentation functions]]&lt;br /&gt;
function output_mt:insert_format(...)&lt;br /&gt;
	self:insert(string.format(...))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
output_mt.join = table.concat&lt;br /&gt;
&lt;br /&gt;
output_mt.__index = output_mt&lt;br /&gt;
&lt;br /&gt;
local function Output()&lt;br /&gt;
	return setmetatable({ n = 0 }, output_mt)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local Latn_pattern = table.concat {&lt;br /&gt;
	&amp;quot;[&amp;quot;,&lt;br /&gt;
	&amp;quot;\n\32-\127&amp;quot;,&lt;br /&gt;
	&amp;quot;\194\160-\194\172&amp;quot;,&lt;br /&gt;
	&amp;quot;\195\128-\195\191&amp;quot;,&lt;br /&gt;
	&amp;quot;\196\128-\197\191&amp;quot;,&lt;br /&gt;
	&amp;quot;\198\128-\201\143&amp;quot;,&lt;br /&gt;
	&amp;quot;\225\184\128-\225\187\191&amp;quot;,&lt;br /&gt;
	&amp;quot;\226\177\160-\226\177\191&amp;quot;,&lt;br /&gt;
	&amp;quot;\234\156\160-\234\159\191&amp;quot;,&lt;br /&gt;
	&amp;quot;\234\172\176-\234\173\175&amp;quot;,&lt;br /&gt;
	&amp;quot;\239\172\128-\239\172\134&amp;quot;,&lt;br /&gt;
	&amp;quot;\239\188\129-\239\188\188&amp;quot;,&lt;br /&gt;
	&amp;quot;–&amp;quot;,&lt;br /&gt;
	&amp;quot;—&amp;quot;,&lt;br /&gt;
	&amp;quot;«&amp;quot;, &amp;quot;»&amp;quot;,&lt;br /&gt;
	&amp;quot;]&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
local get_codepoint = mw.ustring.codepoint&lt;br /&gt;
local function expand_range(start, ending)&lt;br /&gt;
	local lower, higher = get_codepoint(start), get_codepoint(ending)&lt;br /&gt;
	if higher &amp;lt; lower then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local chars = {}&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for codepoint = lower, higher do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		chars[i] = mw.ustring.char(codepoint)&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(chars)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local fun = require &amp;quot;Module:Fun&amp;quot;&lt;br /&gt;
local m_table = require &amp;quot;Module:TableTools&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local script_to_count_mt = {&lt;br /&gt;
	__index = function (self, key)&lt;br /&gt;
		self[key] = 0&lt;br /&gt;
		return 0&lt;br /&gt;
	end,&lt;br /&gt;
	__call = function (self, ...)&lt;br /&gt;
		return setmetatable({}, self)&lt;br /&gt;
	end&lt;br /&gt;
}&lt;br /&gt;
setmetatable(script_to_count_mt, script_to_count_mt)&lt;br /&gt;
&lt;br /&gt;
-- Uses an iterator (such as mw.ustring.gcodepoint) that generates a codepoint&lt;br /&gt;
-- each time it is called with an optional state and another value.&lt;br /&gt;
local function show_scripts(iterator, state, value)&lt;br /&gt;
	local script_to_count = script_to_count_mt()&lt;br /&gt;
	for codepoint in iterator, state, value do&lt;br /&gt;
		local script = Unicode_data.lookup_script(codepoint)&lt;br /&gt;
		script_to_count[script] = script_to_count[script] + 1&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(&lt;br /&gt;
		fun.mapIter(&lt;br /&gt;
			function (count, script)&lt;br /&gt;
				return (&amp;quot;%s (%d)&amp;quot;):format(script, count)&lt;br /&gt;
			end,&lt;br /&gt;
			m_table.sortedPairs(&lt;br /&gt;
				script_to_count,&lt;br /&gt;
				function (script1, script2)&lt;br /&gt;
					return script_to_count[script1] &amp;gt; script_to_count[script2]&lt;br /&gt;
				end)),&lt;br /&gt;
		&amp;quot;, &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_chars_in_scripts(iterator, state, value)&lt;br /&gt;
	local script_to_char_set = {}&lt;br /&gt;
	for codepoint in iterator, state, value do&lt;br /&gt;
		local script = Unicode_data.lookup_script(codepoint)&lt;br /&gt;
		script_to_char_set[script] = script_to_char_set[script] or {}&lt;br /&gt;
		script_to_char_set[script][codepoint] = true&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return script_to_char_set&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function print_char_set_map(script_to_char_set, format, separator)&lt;br /&gt;
	format = format or &amp;quot;%s: %s&amp;quot;&lt;br /&gt;
	separator = separator or &amp;quot;\n&amp;quot;&lt;br /&gt;
	return table.concat(&lt;br /&gt;
		fun.mapIter(&lt;br /&gt;
			function (char_set, script)&lt;br /&gt;
				local char_list = fun.mapIter(&lt;br /&gt;
					function (_, codepoint)&lt;br /&gt;
						return mw.ustring.char(codepoint)&lt;br /&gt;
					end,&lt;br /&gt;
					m_table.sortedPairs(char_set))&lt;br /&gt;
				return (format):format(script, mw.text.nowiki(table.concat(char_list)))&lt;br /&gt;
			end,&lt;br /&gt;
			m_table.sortedPairs(script_to_char_set)),&lt;br /&gt;
		separator)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.show(frame)&lt;br /&gt;
	local expanded_pattern = Latn_pattern&lt;br /&gt;
		:gsub(&amp;quot;%[(.-)%]&amp;quot;, &amp;quot;%1&amp;quot;)&lt;br /&gt;
		:gsub( -- Find two UTF-8-encoded characters separated by hyphen-minus.&lt;br /&gt;
			&amp;quot;([%z\1-\127\194-\244][\128-\191]*)%-([%z\1-\127\194-\244][\128-\191]*)&amp;quot;,&lt;br /&gt;
			function (char1, char2)&lt;br /&gt;
				return expand_range(char1, char2)&lt;br /&gt;
			end)&lt;br /&gt;
	&lt;br /&gt;
	return (&amp;#039;* &amp;lt;div style=&amp;quot;overflow-wrap: break-word;&amp;quot;&amp;gt;%s&amp;lt;/div&amp;gt;&amp;lt;br&amp;gt;%s&amp;#039;)&lt;br /&gt;
		:format(expanded_pattern&lt;br /&gt;
			:gsub(&amp;quot;^%s*&amp;quot;, &amp;quot;&amp;quot;), -- Remove initial &amp;quot;\n &amp;quot; to avoid creating unwanted pre element.&lt;br /&gt;
			show_scripts(mw.ustring.gcodepoint(expanded_pattern)))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_block_info_from_arg(args, arg)&lt;br /&gt;
	local block_name = args[1]&lt;br /&gt;
		or errorf(&amp;quot;Parameter %s is required&amp;quot;, tostring(arg))&lt;br /&gt;
	&lt;br /&gt;
	local block_info = Unicode_data.get_block_info(block_name)&lt;br /&gt;
		or errorf(&amp;quot;The block &amp;#039;%s&amp;#039; could be found&amp;quot;, block_name)&lt;br /&gt;
	&lt;br /&gt;
	return block_info&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_boolean_from_arg(args, arg)&lt;br /&gt;
	return args[arg] and require &amp;quot;Module:Yesno&amp;quot; (args[arg])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.scripts_in_block(frame)&lt;br /&gt;
	local block_info = get_block_info_from_arg(frame.args, 1)&lt;br /&gt;
	local show_block_name = get_boolean_from_arg(frame.args, 2)&lt;br /&gt;
	local script_list = show_scripts(fun.range(block_info[1], block_info[2]))&lt;br /&gt;
	if show_block_name then&lt;br /&gt;
		return (&amp;quot;%s: %s&amp;quot;):format(block_info[3], script_list)&lt;br /&gt;
	else&lt;br /&gt;
		return script_list&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function link_block_name(block_name)&lt;br /&gt;
	if block_name:find &amp;quot; &amp;quot; then&lt;br /&gt;
		return (&amp;quot;[[%s]]&amp;quot;):format(block_name)&lt;br /&gt;
	else&lt;br /&gt;
		return (&amp;quot;[[%s (Unicode block)|%s]]&amp;quot;):format(block_name, block_name)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.scripts_in_blocks(frame)&lt;br /&gt;
	local output = Output()&lt;br /&gt;
	local start = frame.args[1] and tonumber(frame.args[1], 16) or 0&lt;br /&gt;
	local ending = frame.args[2] and tonumber(frame.args[2], 16) or 0x4000&lt;br /&gt;
	&lt;br /&gt;
	local script_data = mw.loadData &amp;quot;Module:Unicode data/scripts&amp;quot;&lt;br /&gt;
	local singles = script_data.singles&lt;br /&gt;
	local ranges = script_data.ranges&lt;br /&gt;
	&lt;br /&gt;
	local function clear (self)&lt;br /&gt;
		for _, key in ipairs(m_table.keysToList(self, false)) do&lt;br /&gt;
			self[key] = nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local counts = {}&lt;br /&gt;
	setmetatable(counts, {&lt;br /&gt;
		__index = {&lt;br /&gt;
			increment = function(self, script_code, amount)&lt;br /&gt;
				self[script_code] = (self[script_code] or 0) + (amount or 1)&lt;br /&gt;
			end,&lt;br /&gt;
			clear = clear,&lt;br /&gt;
		}&lt;br /&gt;
	})&lt;br /&gt;
	local codepoints_per_script = {}&lt;br /&gt;
	setmetatable(codepoints_per_script, {&lt;br /&gt;
		__index = {&lt;br /&gt;
			add = function(self, script_code, codepoint)&lt;br /&gt;
				self[script_code] = self[script_code] or { n = 0 }&lt;br /&gt;
				if self[script_code].n &amp;lt;= 0x20&lt;br /&gt;
						and not (codepoint &amp;lt;= 0x9F and (codepoint &amp;gt;= 0x80&lt;br /&gt;
						or codepoint &amp;lt;= 0x1F)) then&lt;br /&gt;
					if self[script_code].n == 0x20 then&lt;br /&gt;
						local period = (&amp;quot;.&amp;quot;):byte()&lt;br /&gt;
						for _ = 1, 3 do&lt;br /&gt;
							self[script_code].n = self[script_code].n + 1&lt;br /&gt;
							self[script_code][self[script_code].n] = period&lt;br /&gt;
						end&lt;br /&gt;
					else&lt;br /&gt;
						if script_code == &amp;quot;Zinh&amp;quot; then -- probably combining character&lt;br /&gt;
							self[script_code].n = self[script_code].n + 1&lt;br /&gt;
							self[script_code][self[script_code].n] = 0x25CC&lt;br /&gt;
						end&lt;br /&gt;
						self[script_code].n = self[script_code].n + 1&lt;br /&gt;
						self[script_code][self[script_code].n] = codepoint&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end,&lt;br /&gt;
			clear = clear,&lt;br /&gt;
		}&lt;br /&gt;
	})&lt;br /&gt;
	&lt;br /&gt;
	output:insert [[&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Scripts in each Unicode block&lt;br /&gt;
! block !! codepoints !! scripts&lt;br /&gt;
]]&lt;br /&gt;
	&lt;br /&gt;
	for _, block in pairs(mw.loadData &amp;quot;Module:Unicode data/blocks&amp;quot;) do&lt;br /&gt;
		local codepoint = block[1]&lt;br /&gt;
		if codepoint &amp;gt; ending then break end&lt;br /&gt;
		&lt;br /&gt;
		if codepoint &amp;gt;= start then&lt;br /&gt;
			while codepoint &amp;lt;= block[2] do&lt;br /&gt;
				local script = singles[codepoint]&lt;br /&gt;
				local count&lt;br /&gt;
				if script then -- Codepoint is in &amp;quot;singles&amp;quot; map.&lt;br /&gt;
					counts:increment(script)&lt;br /&gt;
					codepoints_per_script:add(script, codepoint)&lt;br /&gt;
					codepoint = codepoint + 1&lt;br /&gt;
					count = 1 -- for potential future use&lt;br /&gt;
				else&lt;br /&gt;
					local range, index = Unicode_data.binary_range_search(codepoint, ranges)&lt;br /&gt;
					if range then -- Codepoint is in &amp;quot;ranges&amp;quot; array.&lt;br /&gt;
						count = 0&lt;br /&gt;
						script = range[3]&lt;br /&gt;
						while codepoint &amp;lt;= range[2] and codepoint &amp;lt;= block[2] do&lt;br /&gt;
							count = count + 1&lt;br /&gt;
							codepoints_per_script:add(script, codepoint)&lt;br /&gt;
							codepoint = codepoint + 1&lt;br /&gt;
						end&lt;br /&gt;
						counts:increment(script, count)&lt;br /&gt;
					else -- Codepoint doesn&amp;#039;t have data; it&amp;#039;s Zzzz.&lt;br /&gt;
						-- Get range immediately above codepoint.&lt;br /&gt;
						while ranges[index][2] &amp;lt; codepoint do&lt;br /&gt;
							index = index + 1&lt;br /&gt;
						end&lt;br /&gt;
						&lt;br /&gt;
						count = 0&lt;br /&gt;
						script = &amp;quot;Zzzz&amp;quot;&lt;br /&gt;
						local range = ranges[index]&lt;br /&gt;
						while codepoint &amp;lt; range[1] and codepoint &amp;lt;= block[2]&lt;br /&gt;
								and not singles[codepoint] do&lt;br /&gt;
							count = count + 1&lt;br /&gt;
							codepoint = codepoint + 1&lt;br /&gt;
						end&lt;br /&gt;
						counts:increment(script, count)&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			output:insert_format([[&lt;br /&gt;
|-&lt;br /&gt;
| %s&lt;br /&gt;
| U+%04X&amp;amp;ndash;U+%04X&lt;br /&gt;
| %s&lt;br /&gt;
]], link_block_name(block[3]), block[1], block[2],&lt;br /&gt;
				table.concat(&lt;br /&gt;
					fun.map(&lt;br /&gt;
						function (count, script)&lt;br /&gt;
							return (&amp;#039;&amp;lt;abbr title=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/abbr&amp;gt; (&amp;lt;span title=&amp;quot;%s&amp;quot;&amp;gt;%d&amp;lt;/span&amp;gt;)&amp;#039;)&lt;br /&gt;
								:format(&lt;br /&gt;
									script_data.aliases[script], script,&lt;br /&gt;
									codepoints_per_script[script]&lt;br /&gt;
										and mw.text.nowiki(mw.ustring.char(&lt;br /&gt;
											unpack(codepoints_per_script[script])))&lt;br /&gt;
										or &amp;quot;&amp;quot;,&lt;br /&gt;
									count)&lt;br /&gt;
						end,&lt;br /&gt;
						m_table.sortedPairs(&lt;br /&gt;
							counts,&lt;br /&gt;
							function (script1, script2)&lt;br /&gt;
								return counts[script1] &amp;gt; counts[script2]&lt;br /&gt;
							end)),&lt;br /&gt;
					&amp;quot;, &amp;quot;))&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- mw.logObject(codepoints_per_script, block[3])&lt;br /&gt;
		counts:clear()&lt;br /&gt;
		codepoints_per_script:clear()&lt;br /&gt;
	end&lt;br /&gt;
	output:insert &amp;quot;|}&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	return output:join()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.chars_in_scripts_in_block(frame)&lt;br /&gt;
	local block_info = get_block_info_from_arg(frame.args, 1)&lt;br /&gt;
	local show_block_name = get_boolean_from_arg(frame.args, 2)&lt;br /&gt;
	local script_char_set_map = print_char_set_map(&lt;br /&gt;
		get_chars_in_scripts(fun.range(block_info[1], block_info[2])))&lt;br /&gt;
	if show_block_name then&lt;br /&gt;
		return (&amp;quot;%s: %s&amp;quot;):format(block_info[3], script_char_set_map)&lt;br /&gt;
	else&lt;br /&gt;
		return script_char_set_map&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.search_for_language_codes(frame)&lt;br /&gt;
	local page_name = frame.args[1] or &amp;quot;English language&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	local success, title_object = pcall(mw.title.new, page_name)&lt;br /&gt;
	if not (success and title_object) then&lt;br /&gt;
		mw.logf(&amp;quot;Could not make title object for &amp;#039;%s&amp;#039;.&amp;quot;, page_name)&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local content = title_object:getContent()&lt;br /&gt;
	&lt;br /&gt;
	local language_codes = {}&lt;br /&gt;
	for lang_template in content:gmatch &amp;quot;{{lang[^}]+&amp;quot; do&lt;br /&gt;
		local template_name = lang_template:match(&amp;quot;{{([^|}]+)&amp;quot;)&lt;br /&gt;
		local language_code&lt;br /&gt;
		if template_name == &amp;quot;lang&amp;quot; then&lt;br /&gt;
			language_code = lang_template:match &amp;quot;{{lang|([^|}]+)&amp;quot;&lt;br /&gt;
		elseif template_name:find &amp;quot;^lang-&amp;quot; then&lt;br /&gt;
			language_code = lang_template:match &amp;quot;{{lang-([^|}]+)&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		if language_code then&lt;br /&gt;
			language_codes[language_code] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return table.concat(m_table.keysToList(language_codes), &amp;quot;, &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Erutuon</name></author>
	</entry>
</feed>