<?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%3ASimpleDebug</id>
	<title>Module:SimpleDebug - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASimpleDebug"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:SimpleDebug&amp;action=history"/>
	<updated>2026-04-09T12:48:59Z</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:SimpleDebug&amp;diff=146793&amp;oldid=prev</id>
		<title>imported&gt;Jmarchn: fix minor bug</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:SimpleDebug&amp;diff=146793&amp;oldid=prev"/>
		<updated>2020-06-16T10:58:15Z</updated>

		<summary type="html">&lt;p&gt;fix minor bug&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--2020-06-16 fix error when vtos(nil), then it showed two nil&lt;br /&gt;
--2020-06-08 if a variable is a function now is displayed as function (before &amp;quot;function&amp;quot;)&lt;br /&gt;
--2020-06-06 fix error which occasionally happens when a value == nil&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
p.s = &amp;#039;&amp;#039;&lt;br /&gt;
p.tab = {&lt;br /&gt;
	oneline = true,&lt;br /&gt;
	allidx = false, &lt;br /&gt;
	}&lt;br /&gt;
p.dec = -1&lt;br /&gt;
p.maxlines = {&lt;br /&gt;
	num = 100,&lt;br /&gt;
	doerror = true,&lt;br /&gt;
	}&lt;br /&gt;
p.enabled = true&lt;br /&gt;
p.nowiki = false&lt;br /&gt;
p.nohtml = false&lt;br /&gt;
p._plaintext = false&lt;br /&gt;
p.counter = false&lt;br /&gt;
&lt;br /&gt;
local LinCount = 0&lt;br /&gt;
local vep = &amp;#039;  •  &amp;#039;&lt;br /&gt;
local function MessRaised (n)&lt;br /&gt;
	return &amp;#039;\n\nIt has been reached to &amp;#039;..n..&amp;#039;, you can change this limit with &amp;quot;maxlines.num&amp;quot;.&amp;#039;&lt;br /&gt;
end	&lt;br /&gt;
local function arrow()&lt;br /&gt;
	return &amp;#039; =&amp;gt; &amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.breakline ()&lt;br /&gt;
	LinCount = LinCount + 1&lt;br /&gt;
	p.s = p.s..&amp;#039;\n\n&amp;#039;&lt;br /&gt;
	if p.counter then&lt;br /&gt;
		p.s = p.s..LinCount..vep&lt;br /&gt;
	end	&lt;br /&gt;
	if (LinCount &amp;gt; p.maxlines.num) and p.maxlines.doerror then&lt;br /&gt;
		p.pa = p.s..MessRaised(p.maxlines.num)&lt;br /&gt;
		error (p.s,0)&lt;br /&gt;
	end	&lt;br /&gt;
end	--breakline&lt;br /&gt;
&lt;br /&gt;
local function CheckWhereName (wn, what)&lt;br /&gt;
	if wn == nil then&lt;br /&gt;
		return &amp;#039;&amp;quot;&amp;#039;..what..&amp;#039;&amp;quot; == nil&amp;#039;&lt;br /&gt;
	elseif (type(wn) == &amp;quot;table&amp;quot;) then&lt;br /&gt;
		return &amp;#039;Table as &amp;quot;&amp;#039;..what..&amp;#039;&amp;quot;!&amp;#039;&lt;br /&gt;
	else&lt;br /&gt;
		return wn	&lt;br /&gt;
	end	&lt;br /&gt;
end --CheckWhereName&lt;br /&gt;
&lt;br /&gt;
function p._plain (text) --Modified from &amp;quot;Module:Plain text&amp;quot;&lt;br /&gt;
	if not text then return end&lt;br /&gt;
	text = mw.text.killMarkers(text)&lt;br /&gt;
		:gsub(&amp;#039;&amp;amp;nbsp;&amp;#039;, &amp;#039; &amp;#039;) --replace nbsp spaces with regular spaces&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;br ?/?&amp;gt;&amp;#039;, &amp;#039;, &amp;#039;) --replace br with commas&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;span.-&amp;gt;(.-)&amp;lt;/span&amp;gt;&amp;#039;, &amp;#039;%1&amp;#039;) --remove spans while keeping text inside&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;b&amp;gt;(.-)&amp;lt;/b&amp;gt;&amp;#039;, &amp;#039;%1&amp;#039;) --remove bold while keeping text inside&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;i&amp;gt;(.-)&amp;lt;/i&amp;gt;&amp;#039;, &amp;#039;%1&amp;#039;) --remove italic while keeping text inside&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;sub&amp;gt;(.-)&amp;lt;/sub&amp;gt;&amp;#039;, &amp;#039;%1&amp;#039;) --remove bold while keeping text inside&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;sup&amp;gt;(.-)&amp;lt;/sup&amp;gt;&amp;#039;, &amp;#039;%1&amp;#039;) --remove bold while keeping text inside&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;.-&amp;gt;.-&amp;lt;.-&amp;gt;&amp;#039;, &amp;#039;&amp;#039;) --strip out remaining tags and the text inside&lt;br /&gt;
		:gsub(&amp;#039;&amp;lt;.-&amp;gt;&amp;#039;, &amp;#039;&amp;#039;) --remove any other tag markup&lt;br /&gt;
		:gsub(&amp;#039;%[%[%s*[Ff]ile%s*:.-%]%]&amp;#039;, &amp;#039;&amp;#039;) --strip out files&lt;br /&gt;
		:gsub(&amp;#039;%[%[%s*[Ii]mage%s*:.-%]%]&amp;#039;, &amp;#039;&amp;#039;) --strip out use of image:&lt;br /&gt;
		:gsub(&amp;#039;%[%[%s*[Cc]ategory%s*:.-%]%]&amp;#039;, &amp;#039;&amp;#039;) --strip out categories&lt;br /&gt;
		:gsub(&amp;#039;%[%[[^%]]-|&amp;#039;, &amp;#039;&amp;#039;) --strip out piped link text&lt;br /&gt;
		:gsub(&amp;#039;[%[%]]&amp;#039;, &amp;#039;&amp;#039;) --then strip out remaining [ and ]&lt;br /&gt;
		:gsub(&amp;quot;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;quot;, &amp;quot;&amp;quot;) --strip out bold italic markup&lt;br /&gt;
		:gsub(&amp;quot;&amp;#039;&amp;#039;&amp;#039;?&amp;quot;, &amp;quot;&amp;quot;) --not stripping out &amp;#039;&amp;#039;&amp;#039;&amp;#039; gives correct output for bolded text in quotes&lt;br /&gt;
		:gsub(&amp;#039;----&amp;#039;, &amp;#039;&amp;#039;) --remove ---- lines&lt;br /&gt;
		:gsub(&amp;quot;^%s+&amp;quot;, &amp;quot;&amp;quot;) --strip leading&lt;br /&gt;
		:gsub(&amp;quot;%s+$&amp;quot;, &amp;quot;&amp;quot;) --and trailing spaces&lt;br /&gt;
		:gsub(&amp;quot;%s+&amp;quot;, &amp;quot; &amp;quot;) --strip redundant spaces&lt;br /&gt;
	return text&lt;br /&gt;
end --plain&lt;br /&gt;
&lt;br /&gt;
function p._plain_len (text)&lt;br /&gt;
	return mw.ustring.len (p._plain(text))&lt;br /&gt;
end	&lt;br /&gt;
	&lt;br /&gt;
function p.plain (frame)&lt;br /&gt;
	return p._plain (frame.args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.plain_len (frame)&lt;br /&gt;
	return p._plain_len (frame.args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function totext (text)&lt;br /&gt;
	if p._plaintext then&lt;br /&gt;
		return p._plain (text)&lt;br /&gt;
	else&lt;br /&gt;
		return text&lt;br /&gt;
	end	&lt;br /&gt;
end --totext&lt;br /&gt;
&lt;br /&gt;
local function NumToStr (N)		&lt;br /&gt;
	if (p.dec == -1) or (N == math.floor(N)) then&lt;br /&gt;
		return tostring(N)&lt;br /&gt;
	else&lt;br /&gt;
		return tostring (math.floor ((N*10^p.dec)+0.5) / (10^p.dec))&lt;br /&gt;
	end	&lt;br /&gt;
end	--NumToStr&lt;br /&gt;
&lt;br /&gt;
local iniTab1Line = true&lt;br /&gt;
function p.containsTab (avar)&lt;br /&gt;
	result = false&lt;br /&gt;
	for k,v in pairs(avar) do&lt;br /&gt;
		if type(v) == &amp;#039;table&amp;#039; then&lt;br /&gt;
			result = true&lt;br /&gt;
			break&lt;br /&gt;
		end	&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end --containsTab&lt;br /&gt;
&lt;br /&gt;
local var&lt;br /&gt;
	&lt;br /&gt;
local function DumTab (tbl, indent)&lt;br /&gt;
	if not indent then indent = 1 end&lt;br /&gt;
	local toprint = &amp;quot; {\r\n&amp;quot;&lt;br /&gt;
	indent = indent + 2 &lt;br /&gt;
	for k, v in pairs(tbl) do&lt;br /&gt;
		toprint = toprint..string.rep(&amp;quot; &amp;quot;, indent)&lt;br /&gt;
		local id = k&lt;br /&gt;
		if (type(k) == &amp;quot;string&amp;quot;) then&lt;br /&gt;
			k = &amp;#039;&amp;quot;&amp;#039;..k..&amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		toprint = toprint..&amp;quot;[&amp;quot;..k..&amp;quot;] = &amp;quot;&lt;br /&gt;
		if (type(v) == &amp;quot;number&amp;quot;) then&lt;br /&gt;
			toprint = toprint..NumToStr(v)..&amp;quot;,\r\n&amp;quot;&lt;br /&gt;
		elseif (type(v) == &amp;quot;string&amp;quot;) then&lt;br /&gt;
			toprint = toprint..&amp;quot;\&amp;quot;&amp;quot;..totext(v)..&amp;quot;\&amp;quot;,\r\n&amp;quot;&lt;br /&gt;
		elseif (type(v) == &amp;quot;table&amp;quot;) then&lt;br /&gt;
			if iniTab1Line and (not p.containsTab (v)) then&lt;br /&gt;
				local wds = &amp;#039;{&amp;#039;&lt;br /&gt;
				for kk,vv in pairs(v) do&lt;br /&gt;
					if (p.tab.allidx == true) or (type(kk) ~= &amp;#039;number&amp;#039;)  then &lt;br /&gt;
						wds = wds..&amp;#039;[&amp;#039;..kk..&amp;#039;]=&amp;#039;..var(vv)..&amp;#039;, &amp;#039;&lt;br /&gt;
					else	&lt;br /&gt;
						wds = wds..var(vv)..&amp;#039;, &amp;#039;&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				toprint = toprint..wds..&amp;quot;},\r\n&amp;quot;&lt;br /&gt;
			else	&lt;br /&gt;
				toprint = toprint..DumTab(v, indent + 2)..&amp;quot;,\r\n&amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			toprint = toprint..&amp;quot;\&amp;quot;&amp;quot;..tostring(v)..&amp;quot;\&amp;quot;,\r\n&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	toprint = toprint..string.rep(&amp;quot; &amp;quot;, indent-2)..&amp;quot;}&amp;quot;&lt;br /&gt;
	return toprint&lt;br /&gt;
end --DumTab&lt;br /&gt;
&lt;br /&gt;
function var (avar)&lt;br /&gt;
	local EndStr = &amp;#039;&amp;#039;&lt;br /&gt;
	if avar == nil then	&lt;br /&gt;
		EndStr = &amp;#039;nil&amp;#039;&lt;br /&gt;
	elseif type(avar) == &amp;#039;table&amp;#039; then&lt;br /&gt;
		if #avar &amp;gt; 0 then&lt;br /&gt;
			p.s = p.s..&amp;#039;\r\n&amp;#039;&lt;br /&gt;
		end	&lt;br /&gt;
		if p.tab.oneline then&lt;br /&gt;
			local wds = &amp;#039;{ &amp;#039;&lt;br /&gt;
			for k,v in pairs(avar) do&lt;br /&gt;
				if (p.tab.allidx == true) or (type(k) ~= &amp;#039;number&amp;#039;)  then &lt;br /&gt;
					wds = wds..&amp;#039;[&amp;#039;..k..&amp;#039;]=&amp;#039;..var(v)..&amp;#039;, &amp;#039;&lt;br /&gt;
				else	&lt;br /&gt;
					wds = wds..var(v)..&amp;#039;, &amp;#039;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			EndStr = wds .. &amp;#039;} &amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			EndStr = DumTab (avar)&lt;br /&gt;
		end	&lt;br /&gt;
	elseif type(avar) == &amp;#039;number&amp;#039; then&lt;br /&gt;
		EndStr = NumToStr (avar)&lt;br /&gt;
	elseif type(avar) == &amp;#039;boolean&amp;#039; then&lt;br /&gt;
		if avar == true then&lt;br /&gt;
			EndStr = &amp;#039;true&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			EndStr = &amp;#039;false&amp;#039;&lt;br /&gt;
		end	&lt;br /&gt;
	elseif type(avar) == &amp;#039;function&amp;#039; then	&lt;br /&gt;
		EndStr = &amp;#039;function&amp;#039;&lt;br /&gt;
	else&lt;br /&gt;
		avar = totext (tostring(avar))&lt;br /&gt;
		if p.nohtml then&lt;br /&gt;
			avar = string.gsub (avar, &amp;quot;&amp;lt;&amp;quot;, &amp;quot;⪡&amp;quot;)&lt;br /&gt;
			avar = string.gsub (avar, &amp;quot;&amp;gt;&amp;quot;, &amp;quot;⪢&amp;quot;)&lt;br /&gt;
		end	&lt;br /&gt;
		EndStr = &amp;#039;&amp;quot;&amp;#039;..avar..&amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	return EndStr&lt;br /&gt;
end --var&lt;br /&gt;
&lt;br /&gt;
function p.w (where)&lt;br /&gt;
	if p.enabled then&lt;br /&gt;
		return CheckWhereName (where, &amp;#039;w&amp;#039;)&lt;br /&gt;
	end	&lt;br /&gt;
end --w&lt;br /&gt;
&lt;br /&gt;
local function varx (avar)&lt;br /&gt;
	iniTab1Line = p.tab.oneline&lt;br /&gt;
	if p.tab.oneline and (type(avar) == &amp;#039;table&amp;#039;) then&lt;br /&gt;
		p.tab.oneline = not p.containsTab(avar)&lt;br /&gt;
	end&lt;br /&gt;
	local ss = var(avar)&lt;br /&gt;
	p.tab.oneline = iniTab1Line&lt;br /&gt;
	return ss&lt;br /&gt;
end --varx&lt;br /&gt;
&lt;br /&gt;
function p.v (...)&lt;br /&gt;
	if p.enabled then&lt;br /&gt;
		local str = &amp;#039;&amp;#039;&lt;br /&gt;
		if #arg == 0 then&lt;br /&gt;
			str = &amp;#039;nil&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			local c = 0&lt;br /&gt;
			for k, i in ipairs(arg) do&lt;br /&gt;
				c = k&lt;br /&gt;
			end	&lt;br /&gt;
			--error (c)&lt;br /&gt;
			for i = 1, #arg do&lt;br /&gt;
				if str ~= &amp;#039;&amp;#039; then&lt;br /&gt;
					str = str..vep&lt;br /&gt;
				end	&lt;br /&gt;
				str = str..varx(arg[i])&lt;br /&gt;
			end	&lt;br /&gt;
		end	&lt;br /&gt;
		return str&lt;br /&gt;
	end	&lt;br /&gt;
end	--v&lt;br /&gt;
&lt;br /&gt;
function p.wv (where, ...)&lt;br /&gt;
	if p.enabled then&lt;br /&gt;
		return CheckWhereName(where,&amp;#039;w&amp;#039;)..arrow()..p.v(unpack(arg))&lt;br /&gt;
	end	&lt;br /&gt;
end	--wv&lt;br /&gt;
&lt;br /&gt;
function p.nv (...)&lt;br /&gt;
	if p.enabled then&lt;br /&gt;
		if math.mod(#arg,2) ~= 0 then&lt;br /&gt;
			EndStr = &amp;#039;Any parameter has not a name or variable&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			local s = &amp;#039;&amp;#039;&lt;br /&gt;
			local IsName = true&lt;br /&gt;
			function Concat(wds)&lt;br /&gt;
				if s ~= &amp;#039;&amp;#039; then&lt;br /&gt;
					if IsName then&lt;br /&gt;
						s = s..vep&lt;br /&gt;
					else	&lt;br /&gt;
						s = s..&amp;#039;: &amp;#039;&lt;br /&gt;
					end	&lt;br /&gt;
				end&lt;br /&gt;
				s = s..wds&lt;br /&gt;
			end&lt;br /&gt;
			for i = 1, #arg do&lt;br /&gt;
				if IsName then&lt;br /&gt;
					Concat (CheckWhereName(arg[i],&amp;#039;n&amp;#039;))&lt;br /&gt;
					IsName = false&lt;br /&gt;
				else	&lt;br /&gt;
					Concat (varx(arg[i]))&lt;br /&gt;
					IsName = true&lt;br /&gt;
				end	&lt;br /&gt;
			end&lt;br /&gt;
			EndStr = s&lt;br /&gt;
		end&lt;br /&gt;
		return EndStr&lt;br /&gt;
	end	&lt;br /&gt;
end --nv&lt;br /&gt;
&lt;br /&gt;
function p.wnv (where, ...)&lt;br /&gt;
	if p.enabled then&lt;br /&gt;
		return CheckWhereName(where,&amp;#039;w&amp;#039;)..arrow()..p.nv (unpack(arg))&lt;br /&gt;
	end	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------&lt;br /&gt;
&lt;br /&gt;
local function EnabAndBl ()&lt;br /&gt;
	if p.enabled then&lt;br /&gt;
		if LinCount &amp;lt; p.maxlines.num then&lt;br /&gt;
			p.breakline ()&lt;br /&gt;
			return true&lt;br /&gt;
		else&lt;br /&gt;
			p.s = p.s..MessRaised(p.maxlines.num)&lt;br /&gt;
			error (p.s)&lt;br /&gt;
			return false&lt;br /&gt;
		end	&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end --EnabAndBl&lt;br /&gt;
&lt;br /&gt;
function p.wtos (where)&lt;br /&gt;
	if EnabAndBl () then&lt;br /&gt;
		p.s = p.s..p.w (where)&lt;br /&gt;
	end	&lt;br /&gt;
end --wtos&lt;br /&gt;
&lt;br /&gt;
function p.vtos (...)&lt;br /&gt;
	if EnabAndBl () then&lt;br /&gt;
		local end_nil_count = arg[&amp;quot;n&amp;quot;] - #arg&lt;br /&gt;
		p.s = p.s..p.v (unpack(arg))&lt;br /&gt;
		if #arg == 0 then&lt;br /&gt;
			end_nil_count = end_nil_count-1&lt;br /&gt;
		end	&lt;br /&gt;
		for i = 1, end_nil_count do&lt;br /&gt;
			p.s = p.s..vep..&amp;#039;nil&amp;#039;&lt;br /&gt;
		end	&lt;br /&gt;
	end	&lt;br /&gt;
end --vtos&lt;br /&gt;
&lt;br /&gt;
function p.wvtos (where, ...)&lt;br /&gt;
	if EnabAndBl () then&lt;br /&gt;
		p.s = p.s..p.wv (where,unpack(arg))&lt;br /&gt;
	end	&lt;br /&gt;
end --wvtos&lt;br /&gt;
&lt;br /&gt;
function p.nvtos (...)&lt;br /&gt;
	if EnabAndBl () then&lt;br /&gt;
		local end_nil_count = arg[&amp;quot;n&amp;quot;] - #arg&lt;br /&gt;
		if end_nil_count &amp;gt; 0 then&lt;br /&gt;
			for i = 1, arg[&amp;quot;n&amp;quot;] do&lt;br /&gt;
				if math.mod(i,2) ~= 0 then&lt;br /&gt;
					p.s = p.s..arg[i]..&amp;#039;: &amp;#039;&lt;br /&gt;
				else&lt;br /&gt;
					p.s = p.s..p.v(arg[i])&lt;br /&gt;
					if i &amp;lt; arg[&amp;quot;n&amp;quot;] then&lt;br /&gt;
						p.s = p.s..vep&lt;br /&gt;
					end	&lt;br /&gt;
				end	&lt;br /&gt;
			end	&lt;br /&gt;
		else&lt;br /&gt;
			p.s = p.s..p.nv (unpack(arg))&lt;br /&gt;
		end	&lt;br /&gt;
	end	&lt;br /&gt;
end --nvtos&lt;br /&gt;
&lt;br /&gt;
function p.wnvtos (where, ...)&lt;br /&gt;
	if EnabAndBl () then&lt;br /&gt;
		local end_nil_count = arg[&amp;quot;n&amp;quot;] - #arg&lt;br /&gt;
		if end_nil_count &amp;gt; 0 then&lt;br /&gt;
			p.s = p.s..where..arrow()&lt;br /&gt;
			for i = 1, arg[&amp;quot;n&amp;quot;] do&lt;br /&gt;
				if math.mod(i,2) ~= 0 then&lt;br /&gt;
					p.s = p.s..arg[i]..&amp;#039;: &amp;#039;&lt;br /&gt;
				else&lt;br /&gt;
					p.s = p.s..p.v(arg[i])&lt;br /&gt;
					if i &amp;lt; arg[&amp;quot;n&amp;quot;] then&lt;br /&gt;
						p.s = p.s..vep&lt;br /&gt;
					end	&lt;br /&gt;
				end	&lt;br /&gt;
			end	&lt;br /&gt;
		else&lt;br /&gt;
			p.s = p.s..p.wnv (where, unpack(arg))&lt;br /&gt;
		end	&lt;br /&gt;
	end	&lt;br /&gt;
end --wnvtos&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Jmarchn</name></author>
	</entry>
</feed>