Module:Buffer/doc: Difference between revisions

Content deleted Content added
save
save
Line 5:
<!-- Please place categories where indicated at the bottom of this page and interwikis at Wikidata (see [[Wikipedia:Wikidata]]) -->
{{TOC right}}
This module was originally developed to optimize string concatenation inas a helper method within [[Module:Asbox]], but canhas bebeen usedgeneralized infor anyall modulemodules.
 
The interface for Module:Buffer objects is similar to that of {{Luaref|HTML_library|mw.html}} objects in that you may build complex strings with independent child nodes. In most cases, you may use Buffer objects like a normal string, including using {{code|..}} operator (though {{luaself|:_}} has the same role, but potentially [[#performance|over 10 times faster than {{code|..}}]]). See also: [[#Calling string, mw.ustring, and mw.text libraries]]
 
Additionally, there are three specialized modes, described further in their respective sections: {{luaself|:stream|plain=y}}, {{luaself|\-HTML|plain=y}}, and {{luaself|pre=Element{{-}}|\|plain=y}}
Buffers can also be appended to {{luaref|HTML library|mw.html}} objects via {{luaref|mw.html:node}} (though not mw.html:wikitext because of type checking). (See also [[#usage with string/mw.text libraries]])
 
Last but not least, this module has an ordered [[#require'Module:Buffer'.__pairs|__pairs]] more thorough than {{luaref|ipairs||y}} and {{luaref|pairs||y}}. (Even reads nil keys!) The <span title='This is a bad Star Trek joke'>logical uniqueness</span> of this iterator may be reason enough to {{luaref|require|assimilate|y}} Module:Buffer.
 
==Basic usage==
Line 28 ⟶ 30:
:''See also {{luaself|:_str|plain=y}} for advanced string conversion.
 
Get Buffer as type {{luaref|string||y}} by performing a function call on the Buffer ''object'' (as opposed to [[#require'Module:Buffer'|a call on the ''Module'']]). Calling a Buffer is basically shorthand for {{luaref|table.concat|args=Buffer, ...}}, or, with no args, {{luaref|tostring|args=Buffer}}. However, if your Buffer contains [[#raw|raw]] objects or out-of-sequence values, then the return string would be the result of {{luaself|Buffer|:_all|empty-buffer:_all|args=Buffer )( ...}} instead.<ref group=note name=raw />
 
BuffersNote canyou alsodo benot appendedneed to string a Buffer object to append it to an {{luaref|HTML library|mw.html|y}} objectsobject via {{luaref|mw.html:node}} (though not mw.html:wikitext because of type checking). (See also [[#usage with string/mw.text libraries]])
However, if your Buffer contains [[#raw|raw]] objects or out-of-sequence values, then the return string would be the result of {{luaself|Buffer|:_all|empty-buffer:_all|args=Buffer )( ...}} instead.<ref group=note name=raw />
 
===Buffer.last_concat===
Line 127 ⟶ 129:
 
Unlike :_out, this does not append the child into the parent. As such, even with the same arguments, it may return a different result than would be obtained from stringing the return of :_out since each parents' ''sep'' is not used to join parent and child. Furthermore, the number of ''generations'' counted includes the current Buffer, whereas the number of "''outs''" in Buffer:_out does not.
 
===Buffer:_c_cc===
 
{{luaself|:_c_cc|args=clear|args=clear, copy, meta}}
 
Nils all keys of the table referenced by {{code|clear}} and unsets its metatable. If no table as ''clear'' evaluates false, this simply purges the cache at {{luaself|.last_concat}}.
 
If given a table to {{code|copy}}, this will duplicate all key-value pairs of ''copy'' into ''clear'', passingcloning any valuetable ofheld typeby table''copy'' throughrecursively {{luaref|mw.clone}}.via Any<code>Buffer:_cc(0, metatablevalue)</code>, andwhich Bufferreturns parenta andnew rawtable referencesinstead areinstead alsoof copiedchanging an existing table.
 
While this may resemble {{luaref|mw.clone}}, there are several differences:
* This sets the metatable of ''clear'' to that of ''copy'' instead of cloning its metatable (or to <code>meta</code>, if given).
* {{luaref|Length operator|Length}} is always conserved (though empty strings may replace some nil keys<ref group=note>
For example, given {{code|lang=lua|{nil, 'string'} }} as ''copy'', {{code|lang=lua|Buffer:_cc(clear, copy)}} makes {{code|lang=lua|#clear}} equal <code>2</code>,
whereas {{code|lang=lua|#mw.clone{nil, 'string'} }} equals <code>0</code> (as of March 2015).
This replicates length by filling clear to copy's length and then setting those keys nil when such would not trigger recalculation.
As a result, any keys which would resize ''clear'' when set nil are left as empty strings. Such should be fairly rare;
given every combination of positions for a single nil key for all lengths between 2 and 32 (inclusive), only 8.39 percent such tables would have a nil copied as empty string instead.
Also note that tables returned by {{code|lang=lua|Buffer:_(0, copy)}} have length declared on creation instead, and thus won't have extra strings attached.
The odds can be estimated using <math>y {{=}} 0.5 / \sqrt{x}</math>, where <math>y</math> is the upper limit that an arbitrary nil key from ''copy'' of length ranging from 1 to <math>x</math> is imaged as an empty string.</ref>)
* All values are set via {{luaself|rawset}} and iterated without invoking any __pairs {{luaref|Metatables|metamethod|y}}.
* Also copies Buffer parent and [[#raw|raw]] settings (which are stored externally)
 
If ''copy'' is not a table, then it will be inserted as the first index of the ''clear''ed table so long as ''copy'' is not nil or false. Passing {{code|lang=lua|true}} as ''copy'' is equivalent to passing the Buffer itself.
 
To obtain the table of key-value pairs left as empty strings in the previous copy op, simply call this again with any same value passed to both ''clear'' and ''copy'' (as long as they do not evaluate false).
 
===Buffer:_parent===
Line 153 ⟶ 180:
 
If passed any args, they will be passed to the current parent via Buffer:getParent as a "parting gift". In either case, returns to current Buffer.
 
===Buffer:_c===
 
{{luaself|:_c|args=clear|args=clear, copy}}
 
Nils all keys of the table referenced by {{code|clear}} and unsets its metatable. If no table as ''clear'', this simply purges the cache at {{luaself|.last_concat}}.
 
If given a table to {{code|copy}}, this will duplicate all key-value pairs of ''copy'' into ''clear'', passing any value of type table through {{luaref|mw.clone}}. Any metatable and Buffer parent and raw references are also copied.
 
If ''copy'' is not a table, then it will be inserted as the first index of the ''clear''ed table so long as ''copy'' is not nil or false.
 
==Stream mode==
Line 171 ⟶ 188:
Switches the Buffer to stream mode. In this mode, the [[#call Buffer object|Buffer call]] operation, instead of returning a string, now acts as streamlined version of {{luaself|:_}}.
 
When streaming, you maycan append a sequence of string (and table) literals with nothing between them (or only {{luaref|Character class|ASCII space chars|y}} if desired). For example, both A and B will produce identical strings:
{{#tag:syntaxhighlight|local A = prequire'Module:Buffer':stream'A string of text may flow''with nothing between each string' 'or perhaps only a space'
'or even tab and line-break characters''and continue to append individually''for use with a joiner'
 
local B = prequire'Module:Buffer':_'A string of text may flow':_'with nothing between each string' :_ 'or perhaps only a space'
:_'or even tab and line-break characters':_'and continue to append individually':_'for use with a joiner'
 
Line 184 ⟶ 201:
}|lang=lua}}
 
Aside from saving two keystrokes per stringop, this mode runs about [[#performance|50 percent faster]] than {{code|:_|lang=lua}} (which, saysin aturn, lotis consideringover :_10 is muchtimes faster than the {{code|.. op|lang=lua}} for long strings).
 
Also, Lua numbers
Keep in mind that Lua numbers<ref group=note>It is best practice to pass number ''strings'' instead of a passing a number literals (i.e. {{code|lang=lua|Buffer:stream'1'}} instead of {{code|lang=lua|Buffer:stream(1)}}). Such improves performance (and is perhaps more aesthetically pleasing in this mode).</ref>named variables are too shy to [[skinny dip]] in a Buffer stream and must wear parenthesis {{code|lang=lua|()}} as with any {{luaref|Function calls|function call|y}}.
and named variables are too shy to [[skinny dip]] in a Buffer stream and must wear parenthesis {{code|lang=lua|()}} as with any {{luaref|Function calls|function call|y}}.
 
'''Returning to normal mode'''<br/>
No special action is needed to exit this mode. The normal call to string op is restored upon the use of any regular Buffer function or any operation which coerces the Buffer into a string.<ref group=note>No explicit trigger to exit stream mode has been programmed for {{luaself|pre=Element{{ndash}}|\}} functions (including Buffer-HTML redirects). Stringing an Element-Buffer without its outer HTML-Buffer was deemed uncommon enough such that the inconvience of exiting via using <code>:_()</code> on the last item was outweighed by the [[#performance]] penalty that may result from modifying the specialized functions.</ref>
 
===Buffer:stream:each===
 
{{luaself|:stream:each|args=...}}
 
Appends an undetermined number of [[#valid|valid]] values.
 
While analogous to {{luaref|mw.html:wikitext|plain=y}}, one distinguishing point (other than being [[#performance|twice as fast]] and able to [[#Buffer:_|handle tables and booleans]]) is that this does ''not'' stop at the first ''nil'' value. In short, something like {{code|lang=lua|:wikitext('string1', varName, 'string2')}} can be replaced with {{code|lang=lua|:each('string1', {varName, 'string2'})}} when <code>varName</code> is either a string or nil.
 
==HTML extension==
Line 230 ⟶ 253:
Element-Buffers have the same metatable as normal Buffer objects, so [[#call Buffer object|calling it]] will string it in the same manner.
 
The string returned is analogous to the valuethat returned by the [[JavaScript]] DOM method [http://www.w3schools.com/jsref/prop_html_innerhtml.asp "innerHTML"] DOM property in [[JavaScript]]. In other words, when strung, it is the contents of the Buffer-HTML object without the "outerHTML" or tag (though it will include the outer Buffer-HTML when appended via {{luaref|mw.html:node}}).
 
You may use most Buffer object functionfunctions normally, however those which have a Buffer-HTML version (such as {{luaself|\-HTML:_out}}) will instead behave as though used on the [[#Buffer-HTML|outer HTML object]].<ref group=note>While Buffer-HTML objects may use [[#global functions]], there is no separate Buffer-HTML version. In other words, the self-action of a global function on an Element-Buffer is <u>not</u> redirected to the outer Buffer-HTML object.</ref> Also, {{luaself|pre-Element|:_inHTML}} has been modified as described in that section.
 
Additionally, you may chain any mw.html object function directly on an Element-Buffer. With the exception of {{luaself|pre=Element{{ndash}}|:tag}} and {{luaself|pre=Element{{ndash}}|:done}}, the mw.html function has been placed in a wrapper function that merely redirects the self-action to the outside Buffer-HTML.<ref group=note>{{luaref|mw.html:allDone}} is doubly wrapped for Element-Buffers. The inner wrapper sets a Buffer parent reference as described at {{luaself|:_inHTML}}.</ref>
 
Concatenate an Element-Buffer to another value with the {{code|lang=lua|..}} operator to return the result inside the tag, such that:
{{#tag:syntaxhighlight|
local Buff = require'Module:Buffer':_inHTML'div'{'Section ',color='red'}
return {Buff..1,Buff..2,Buff..3}
|lang=lua}}
 
Can be a rapid way of generating:
{{#tag:syntaxhighlight|
local section = {}
for k = 1, 3 do
table.insert(section, tostring(mw.html.create'div':css{color='red'}:wikitext('Section ', k)))
end
return section
|lang=lua}}
 
====Element-Buffer:done====
Line 247 ⟶ 285:
 
===ipairs with HTML-Buffer===
:''See also [[#Using 'all' pairs_pairs outside of buffer]] for more details about Module:Buffer's custom iterator.
 
<pre>
Line 280 ⟶ 318:
 
 
==require'Module:Buffer'.__pairs==
==Using 'all' pairs outside of buffer==
 
{{anchor|library}}
==StringCalling string, mw.ustring, and mw.text functionslibraries==
 
{{anchor|tips|Tips}}
Line 303 ⟶ 341:
::versus: {{code|lang=lua|Buffer:_nil('0', condition and 'replacement' or false):_(condition and 'Front', 1):getParent(condition and 'from child'):_B(child)}}.
 
'''For {{luaself|:_c_cc}}'''
 
* If the table reference passed as {{code|clear}} was appended [[#raw|raw]] in multiple positions, this is akin to performing {{luaself|:_nil}} at all positions simultaneously. (May be easier than trying to come up with a {{luaref|string.gsub}} pattern)