Jump to content
 







Main menu
   


Navigation  



Main page
Contents
Current events
Random article
About Wikipedia
Contact us
Donate
 




Contribute  



Help
Learn to edit
Community portal
Recent changes
Upload file
 








Search  

































Create account

Log in
 









Create account
 Log in
 




Pages for logged out editors learn more  



Contributions
Talk
 

















Module:Val: Difference between revisions






Аԥсшәа
العربية

Azərbaycanca
تۆرکجه
Basa Bali

Беларуская (тарашкевіца)

Буряад
Català
Чӑвашла
Čeština
الدارجة
Euskara
فارسی
Gaeilge
Galego

Hausa
Հայերեն
ि
Ilokano
Bahasa Indonesia
Italiano
Jawa

Lietuvių
Ligure
ि
Македонски


 / Mìng-dĕ̤ng-nḡ
Мокшень

Na Vosa Vakaviti


Oʻzbekcha / ўзбекча

Português
Română
Scots
Shqip
Simple English
Slovenščina
کوردی
Српски / srpski
Suomi
Svenska
ி
Taqbaylit
 
Tetun

Türkçe
Українська
اردو
Vèneto
Tiếng Vit


 

Edit links
 









Module
Talk
 

















Read
View source
View history
 








Tools
   


Actions  



Read
View source
View history
 




General  



What links here
Related changes
Upload file
Special pages
Permanent link
Page information
Get shortened URL
Download QR code
Wikidata item
 




Print/export  



Printable version
 
















Appearance
   

 





Help

Permanently protected module

From Wikipedia, the free encyclopedia
 


Browse history interactively
 Previous editNext edit 
Content deleted Content added
a built-in unit can be an alias for a unit defined in convert
handle Module:Su here to slightly reduce overhead, and default to align=right
Line 256: Line 256:

end

end

return result

return result

end


local function sup_sub(sup, sub, align)

-- Return the same result as Module:Su except val defaults to align=right.

if align == 'l' or align == 'left' then

align = 'left'

elseif align == 'c' or align == 'center' then

align = 'center'

else

align = 'right'

end

return '<span style="display:inline-block;margin-bottom:-0.3em;vertical-align:-0.4em;line-height:1.2em;font-size:85%;text-align:' ..

align .. '">' .. sup .. '<br />' .. sub .. '</span>'

end

end



Line 292: Line 305:

local uncL = uncertainty.lower.clean

local uncL = uncertainty.lower.clean

if uncL then

if uncL then

local mSu = require('Module:Su')._main -- sup/sub format

uncU = delimit('+', uncU, fmt) .. (uncertainty.upper.errend or '')

uncU = delimit('+', uncU, fmt) .. (uncertainty.upper.errend or '')

uncL = delimit('−', uncL, fmt) .. (uncertainty.lower.errend or '')

uncL = delimit('−', uncL, fmt) .. (uncertainty.lower.errend or '')

Line 299: Line 311:

uncL = uncL .. unit_table.text

uncL = uncL .. unit_table.text

end

end

unc_text = '<span style="margin-left:0.3em;">' .. mSu(uncU, uncL) .. '</span>'

unc_text = '<span style="margin-left:0.3em;">' .. sup_sub(uncU, uncL, misc_tbl.align) .. '</span>'

else

else

if uncertainty.upper.parens then

if uncertainty.upper.parens then

Line 395: Line 407:

suffix = args.s,

suffix = args.s,

fmt = args.fmt or '',

fmt = args.fmt or '',

align = args.a,

nocat = args.nocategory,

nocat = args.nocategory,

sortable = args.sortable,

sortable = args.sortable,


Revision as of 10:45, 22 July 2015

This module implements {{Val}}.

The following modules are developed:

Use {{val/sandbox}} for testing, for example:

-- For Template:Val, output a number and optional unit.
-- Format options include scientific and uncertainty notations.

local delimit_groups = require('Module:Gapnum').groups

local function valerror(msg, nocat)
 -- Return formatted message for {{val}} errors.
 if is_test_run then  -- LATER remove
  return 'Error: "' .. msg .. '"'
 end
 local ret = mw.html.create('strong')
       :addClass('error')
       :wikitext('Error in &#123;&#123;Val&#125;&#125;: ' .. msg)
 -- Not in talk, user, user_talk, or wikipedia_talk
 if not nocat and not mw.title.getCurrentTitle():inNamespaces(1,2,3,5) then
  ret:wikitext('[[Category:Pages with incorrect formatting templates use]]')
 end
 return tostring(ret)
end

local function extract_number(index, numbers, args)
 -- Extract number from args[index] and store result in numbers[index]
 -- and return true if no argument or if argument is valid.
 -- The result is a table which is empty if there was no specified number.
 -- Input like 1e3 is regarded as invalid; should use e=3 parameter.
 -- Input commas are removed so 1,234 is the same as 1234.
 local result = {}
 local arg = args[index]  -- has been trimmed
 if arg and arg ~= '' then
  arg = arg:gsub(',', '')
  if arg:sub(1, 1) == '(' and arg:sub(-1) == ')' then
   result.parens = true
   arg = arg:sub(2, -2)
  end
  local minus = '−'
  local isnegative, propersign, prefix
  prefix, arg = arg:match('^(.-)([%d.]+)$')
  local value = tonumber(arg)
  if not value then
   return false
  end
  if arg:sub(1, 1) == '.' then
   arg = '0' .. arg
  end
  if prefix == '' then
   -- Ignore.
  elseif prefix == '±' then
   -- Display for first number, ignore for others.
   if index == 1 then
    propersign = '±'
   end
  elseif prefix == '+' then
   propersign = '+'
  elseif prefix == '-' or prefix == minus then
   propersign = minus
   isnegative = true
  else
   return false
  end
  result.clean = arg
  result.sign = propersign or ''
  result.value = isnegative and -value or value
 end
 numbers[index] = result
 return true
end

local function get_scale(text, ucode)
 -- Return the value of text as a number, or throw an error.
 -- This supports extremely basic expressions of the form:
 --   a / b
 --   a ^ b
 -- where a and b are numbers or 'pi'.
 local n = tonumber(text)
 if n then
  return n
 end
 n = text:gsub('pi', math.pi)
 for _, op in ipairs({ '/', '^' }) do
  local a, b = n:match('^(.-)' .. op .. '(.*)$')
  if a then
   a = tonumber(a)
   b = tonumber(b)
   if a and b then
    if op == '/' then
     return a / b
    elseif op == '^' then
     return a ^ b
    end
   end
   break
  end
 end
 error('Unit "' .. ucode .. '" has invalid scale "' .. text .. '"')
end

local function get_builtin_unit(ucode, definitions)
 -- Return table of information for the specified built-in unit, or nil if not known.
 -- Each defined unit code must be followed by two spaces (not tab characters).
 local _, pos = definitions:find('\n' .. ucode .. '  ', 1, true)
 if pos then
  local endline = definitions:find('\n', pos, true)
  if endline then
   local result = {}
   local n = 0
   local text = definitions:sub(pos, endline - 1):gsub('%s%s+', '\t')
   for item in (text .. '\t'):gmatch('(%S.-)\t') do
    if item == 'ALIAS' then
     result.alias = true
    elseif item == 'ANGLE' then
     result.isangle = true
     result.nospace = true
    elseif item == 'NOSPACE' then
     result.nospace = true
    elseif item == 'SI' then
     result.si = true
    else
     n = n + 1
     if n == 1 then
      result.symbol = item
     elseif n == 2 then
      result.link = item
     elseif n == 3 then
      result.scale = get_scale(item, ucode)
     else
      break
     end
    end
   end
   if n >= 2 or (n >= 1 and result.alias) then
    return result
   end
   -- Ignore invalid definition, treating it as a comment.
  end
 end
end

local function convert_lookup(ucode, value, scaled_top, want_link, si, options)
 local lookup = require('Module:Convert/sandbox')._unit
 return lookup(ucode, {
   value = value,
   scaled_top = scaled_top,
   link = want_link,
   si = si,
   sort = options.want_sort,
  })
end

local function get_unit(ucode, value, scaled_top, options)
 local want_link = options.want_link
 if scaled_top then
  want_link = options.want_per_link
 end
 local data = mw.loadData('Module:Val/units')
 local result = options.want_longscale and
  get_builtin_unit(ucode, data.builtin_units_long_scale) or
  get_builtin_unit(ucode, data.builtin_units)
 local si, use_result
 if result then
  use_result = true
  if result.alias then
   ucode = result.symbol
   use_result = false
  end
  if result.scale then
   value = value * result.scale
  end
  if result.si then
   si = { result.symbol, result.link }
   use_result = false
  end
 end
 local convert_unit = convert_lookup(ucode, value, scaled_top, want_link, si, options)
 if use_result then
  if want_link then
   result.text = '[[' .. result.link .. '|' .. result.symbol .. ']]'
  else
   result.text = result.symbol
  end
  result.sortkey = convert_unit.sortspan
  result.scaled_top = value
 else
  result = {
   text = convert_unit.text,
   sortkey = convert_unit.sortspan,
   scaled_top = convert_unit.scaled_value,
  }
 end
 return result
end

local function makeunit(value, options)
 -- Return table of information for the requested unit and options, or
 -- return nil if no unit.
 options = options or {}
 local unit
 local ucode = options.u
 local percode = options.per
 if ucode then
  unit = get_unit(ucode, value, nil, options)
 elseif percode then
  unit = { nospace = true, scaled_top = value }
 else
  return nil
 end
 local text = unit.text or ''
 local sortkey = unit.sortkey
 if percode then
  local function bracketed(code, text)
   return code:find('[*./]') and '(' .. text .. ')' or text
  end
  local perunit = get_unit(percode, 1, unit.scaled_top, options)
  text = (ucode and bracketed(ucode, text) or '') ..
    '/' .. bracketed(percode, perunit.text)
  sortkey = perunit.sortkey
 end
 if not unit.nospace then
  text = '&nbsp;' .. text
 end
 return { text = text, isangle = unit.isangle, sortkey = sortkey }
end

local function delimit(sign, numstr, fmt)
 -- Return sign and numstr (unsigned digits or '.' only) after formatting.
 -- Four-digit integers are not formatted with gaps.
 fmt = (fmt or ''):lower()
 if fmt == 'none' or (fmt ~= 'commas' and #numstr == 4 and numstr:match('^%d+$')) then
  return sign .. numstr
 end
 -- Group number by integer and decimal parts.
 -- If there is no decimal part, delimit_groups returns only one table.
 local ipart, dpart = delimit_groups(numstr)
 local result
 if fmt == 'commas' then
  result = sign .. table.concat(ipart, ',')
  if dpart then
   result = result .. '.' .. table.concat(dpart)
  end
 else
  -- Delimit with a small gap by default.
  local groups = {}
  groups[1] = table.remove(ipart, 1)
  for _, v in ipairs(ipart) do
   table.insert(groups, '<span style="margin-left:.25em">' .. v .. '</span>')
  end
  if dpart then
   table.insert(groups, '.' .. table.remove(dpart, 1))
   for _, v in ipairs(dpart) do
    table.insert(groups, '<span style="margin-left:.25em">' .. v .. '</span>')
   end
  end
  result = table.concat(groups)
  -- LATER Is the following needed?
  --       It is for compatibility with {{val}} which uses {{val/delimitnum}}.
  result = '<span style="white-space:nowrap">' .. sign .. result .. '</span>'
 end
 return result
end

local function sup_sub(sup, sub, align)
 -- Return the same result as Module:Su except val defaults to align=right.
 if align == 'l' or align == 'left' then
  align = 'left'
 elseif align == 'c' or align == 'center' then
  align = 'center'
 else
  align = 'right'
 end
 return '<span style="display:inline-block;margin-bottom:-0.3em;vertical-align:-0.4em;line-height:1.2em;font-size:85%;text-align:' ..
  align .. '">' .. sup .. '<br />' .. sub .. '</span>'
end

local function _main(number, uncertainty, unit_spec, misc_tbl)
 local e_10 = misc_tbl.e
 local fmt = misc_tbl.fmt
 -- Unit.
 local sortkey
 local want_sort = not (misc_tbl.sortable == 'off')
 local sort_value = want_sort and ((number.value or 1) * (e_10.value and 10^e_10.value or 1)) or 1
 local unit_table = makeunit(sort_value, {
      u = unit_spec.u,
      want_link = unit_spec.want_link,
      per = unit_spec.per,
      want_per_link = unit_spec.want_per_link,
      want_longscale = unit_spec.want_longscale,
      want_sort = want_sort,
     })
 if unit_table then
  if want_sort then
   sortkey = unit_table.sortkey
  end
 else
  unit_table = { text = '' }
  if want_sort then
   sortkey = convert_lookup('dummy', sort_value, nil, nil, nil, { want_sort = true }).sortspan
  end
 end
 -- Uncertainty.
 local unc_text
 local paren_left, paren_right = '', ''
 local uncU = uncertainty.upper.clean
 if uncU and number.clean then
  -- Cannot enter an uncertainty without a preceding number, however, if it were
  -- possible, the uncertainty should be ignored to avoid displaying junk.
  local uncL = uncertainty.lower.clean
  if uncL then
   uncU =  delimit('+', uncU, fmt) .. (uncertainty.upper.errend or '')
   uncL =  delimit('−', uncL, fmt) .. (uncertainty.lower.errend or '')
   if unit_table.isangle then
    uncU = uncU .. unit_table.text
    uncL = uncL .. unit_table.text
   end
   unc_text = '<span style="margin-left:0.3em;">' .. sup_sub(uncU, uncL, misc_tbl.align) .. '</span>'
  else
   if uncertainty.upper.parens then
    unc_text = '(' .. uncU .. ')'  -- template does not delimit
   else
    unc_text = '<span style="margin-left:0.3em;margin-right:0.15em">±</span>' .. delimit('', uncU, fmt)
    if e_10.clean then
     paren_left = '('
     paren_right = ')'
    end
   end
   if uncertainty.errend then
    unc_text = unc_text .. uncertainty.errend
   end
   if unit_table.isangle then
    unc_text = unc_text .. unit_table.text
   end
  end
 end
 local e_text, n_text
 if number.clean then
  n_text = delimit(number.sign, number.clean, fmt) .. (number.nend  or '')
  if not uncertainty.upper.parens and unit_table.isangle then
   n_text = n_text .. unit_table.text
  end
 else
  n_text = ''
  if not e_10.clean then
   e_10.clean = '0'
   e_10.sign = ''
  end
 end
 if e_10.clean then
  e_text = '10<sup>' .. delimit(e_10.sign, e_10.clean, fmt) .. '</sup>'
  if number.clean then
   e_text = '<span style="margin-left:0.25em;margin-right:0.15em">×</span>' .. e_text
  end
 else
  e_text = ''
 end
 return table.concat({
   '<span class="nowrap">',
   sortkey or '',
   misc_tbl.prefix or '',
   paren_left,
   n_text,
   unc_text or '',
   paren_right,
   e_text,
   unit_table.isangle and '' or unit_table.text,
   misc_tbl.suffix or '',
   '</span>'
  })
end

local function main(frame)
 local getArgs = require('Module:Arguments').getArgs
 local args = getArgs(frame, {wrappers = { 'Template:Val', 'Template:Val/sandboxlua' }})
 local nocat = args.nocategory
 local numbers = {}
 local checks = {
  -- index, description
  { 1, 'first parameter' },
  { 2, 'second parameter' },
  { 3, 'third parameter' },
  { 'e', 'exponent parameter (<b>e</b>)' },
 }
 for _, item in ipairs(checks) do
  if not extract_number(item[1], numbers, args) then
   return valerror(item[2] .. ' is not a valid number.', nocat)
  end
 end
 if args.u and args.ul then
  return valerror('unit (<b>u</b>) and unit with link (<b>ul</b>) are both specified, only one is allowed.', nocat)
 end
 if args.up and args.upl then
  return valerror('unit per (<b>up</b>) and unit per with link (<b>upl</b>) are both specified, only one is allowed.', nocat)
 end
 local number = numbers[1]
 local uncertainty = {
   upper = numbers[2],
   lower = numbers[3],
   errend = args.errend,
  }
 local unit_spec = {
   u = args.ul or args.u,
   want_link = args.ul ~= nil,
   per = args.upl or args.up,
   want_per_link = args.upl ~= nil,
   want_longscale = (args.longscale or args.long_scale or args['long scale']) == 'on',
  }
 local misc_tbl = {
   e = numbers.e,
   prefix = args.p,
   suffix = args.s,
   fmt = args.fmt or '',
   align = args.a,
   nocat = args.nocategory,
   sortable = args.sortable,
  }
 number.nend = args['end']
 uncertainty.upper.errend = args['+errend']
 uncertainty.lower.errend = args['-errend']
 return _main(number, uncertainty, unit_spec, misc_tbl)
end

return { main = main, _main = _main }

Retrieved from "https://en.wikipedia.org/w/index.php?title=Module:Val&oldid=672562748"

Hidden category: 
Wikipedia template-protected modules
 



This page was last edited on 22 July 2015, at 10:45 (UTC).

This version of the page has been revised. Besides normal editing, the reason for revision may have been that this version contains factual inaccuracies, vandalism, or material not compatible with the Creative Commons Attribution-ShareAlike License.



Privacy policy

About Wikipedia

Disclaimers

Contact Wikipedia

Code of Conduct

Developers

Statistics

Cookie statement

Mobile view



Wikimedia Foundation
Powered by MediaWiki