|
|
| (One intermediate revision by the same user not shown) |
| Line 1: |
Line 1: |
| -- Which icon stands for an instrument. | | -- Which icon stands for an instrument. |
| -- | | -- |
| -- An instrument is recorded as it was played: "5-string banjo", not "banjo". | | -- The module itself lives in the repository, at |
| -- That detail is the point. Whether Cory brought a five-string or a tenor, | | -- extensions/PickiPediaContent/lua/pickipedia/instruments.lua, and is loaded |
| -- whether the banjo is Scruggs or clawhammer, is a fact about the cut, and | | -- from there through Scribunto's external library paths. That is deliberate: |
| -- rounding it off to fit a picture would be throwing away the better half of | | -- a module edited here is code that nothing reviews, nothing keeps history |
| -- what we know.
| | -- for, and nothing can revert. In the repository it gets a pull request, a |
| | -- history, a revert, and tests that run before it ships. |
| -- | | -- |
| -- But there are eleven icons and there will never be one per variant. So the | | -- So change it there, not here. An edit to this page would be overridden by |
| -- name and the icon are separated: the name is kept and shown verbatim, and
| | -- nothing and reviewed by nobody -- it would simply take effect, which is the |
| -- this decides which family the name belongs to. A name with no family shows
| | -- problem. |
| -- no icon, which is the correct outcome for a cello -- far better than the
| |
| -- broken image that "File:Instrument-icon-cello.png" produced before.
| |
| | |
| local p = {}
| |
| | |
| -- The icons that exist, as File:Instrument-icon-<family>.png.
| |
| local FAMILIES = {
| |
| "autoharp", "banjo", "bass", "dobro", "fiddle", "guitar",
| |
| "mandolin", "percussion", "tin whistle", "ukulele", "vocals",
| |
| }
| |
| | |
| -- Drawn at a playing angle rather than upright.
| |
| local ROTATED = {
| |
| banjo = true, guitar = true, mandolin = true, ukulele = true,
| |
| }
| |
| | |
| -- Names that do not contain their family's name. A name that does contain it
| |
| -- needs no entry: "5-string banjo", "tenor guitar" and "clawhammer banjo"
| |
| -- are all found without being listed.
| |
| --
| |
| -- Matched against the whole name first, then word by word, so "bass guitar"
| |
| -- lands on bass rather than on guitar.
| |
| local ALIASES = {
| |
| ["bass guitar"] = "bass",
| |
| ["electric bass"] = "bass",
| |
| ["upright"] = "bass",
| |
| ["double bass"] = "bass",
| |
| ["doghouse"] = "bass",
| |
| | |
| ["violin"] = "fiddle",
| |
| ["viola"] = "fiddle",
| |
| | |
| ["drums"] = "percussion",
| |
| ["drum"] = "percussion",
| |
| ["washboard"] = "percussion",
| |
| ["spoons"] = "percussion",
| |
| ["bones"] = "percussion",
| |
| | |
| ["vocal"] = "vocals",
| |
| ["voice"] = "vocals",
| |
| ["singing"] = "vocals",
| |
| ["throatsinging"] = "vocals",
| |
| ["throat singing"] = "vocals",
| |
| ["harmony"] = "vocals",
| |
| ["spoken word"] = "vocals",
| |
| | |
| ["whistle"] = "tin whistle",
| |
| ["six-whistle"] = "tin whistle",
| |
| ["pennywhistle"] = "tin whistle",
| |
| ["flute"] = "tin whistle",
| |
| ["recorder"] = "tin whistle",
| |
| | |
| ["resonator"] = "dobro",
| |
| ["squareneck"] = "dobro",
| |
| | |
| ["uke"] = "ukulele",
| |
| }
| |
| | |
| local function normalise( name )
| |
| return ( tostring( name or "" ):lower():gsub( "%s+", " " ):gsub( "^ ", "" ):gsub( " $", "" ) )
| |
| end
| |
| | |
| -- Does needle appear in haystack as a whole word or phrase? Without this,
| |
| -- "bass" would be found inside "bassoon" and a bassoon would be a bass.
| |
| local function containsPhrase( haystack, needle )
| |
| local from = 1
| |
| while true do
| |
| local start, stop = haystack:find( needle, from, true )
| |
| if not start then return false end
| |
| local before = start == 1 and "" or haystack:sub( start - 1, start - 1 )
| |
| local after = haystack:sub( stop + 1, stop + 1 )
| |
| if not before:match( "%a" ) and not after:match( "%a" ) then
| |
| return true
| |
| end
| |
| from = start + 1
| |
| end
| |
| end
| |
| | |
| --- The family an instrument belongs to.
| |
| --
| |
| -- @param name an instrument as somebody wrote it down.
| |
| -- @return the family name, or "" when nothing here covers it.
| |
| function p._family( name )
| |
| name = normalise( name )
| |
| if name == "" then return "" end
| |
| | |
| -- The whole name, exactly. This is what lets "bass guitar" be a bass:
| |
| -- it is settled before anything goes looking for family names inside.
| |
| for _, family in ipairs( FAMILIES ) do
| |
| if name == family then return family end
| |
| end
| |
| if ALIASES[ name ] then return ALIASES[ name ] end
| |
| | |
| -- A family named within the name. Longest first, so a hypothetical
| |
| -- "tin whistle" beats a shorter match that overlaps it.
| |
| local byLength = {}
| |
| for _, family in ipairs( FAMILIES ) do table.insert( byLength, family ) end
| |
| table.sort( byLength, function( a, b ) return #a > #b end )
| |
| for _, family in ipairs( byLength ) do
| |
| if containsPhrase( name, family ) then return family end
| |
| end
| |
| | |
| -- Failing that, an aliased word inside the name: "wood flute", "electric
| |
| -- fiddle", "tenor uke".
| |
| for alias, family in pairs( ALIASES ) do
| |
| if containsPhrase( name, alias ) then return family end
| |
| end
| |
| | |
| return ""
| |
| end
| |
| | |
| --- The icon for an instrument, as wikitext, or nothing.
| |
| -- | | -- |
| -- @param name the instrument, shown verbatim in the tooltip. | | -- Documentation, including how a name becomes an icon and how to add one: |
| -- @param size pixel height of the icon.
| | -- Template:ShowInstrument, and the README beside the Lua. |
| -- @param tuck when set, pull the icon back over the name it follows -- the
| |
| -- tight inline form used beside a musician's link.
| |
| function p._badge( name, size, tuck )
| |
| local family = p._family( name )
| |
| if family == "" then return "" end
| |
| | |
| size = tonumber( size ) or 20
| |
| local outer = "display:inline-block;"
| |
| if tuck then
| |
| outer = outer .. "position: relative;top: -4px;left: -2px;width: 9px;"
| |
| end
| |
| if ROTATED[ family ] then
| |
| outer = outer .. "transform:rotate(-30deg);"
| |
| end
| |
| | |
| local label = normalise( name )
| |
| return '<span title="' .. label .. '" style="' .. outer .. '">'
| |
| .. '<span style="display:inline-block;width:' .. ( size + 2 )
| |
| .. "px;height:" .. ( size + 2 ) .. 'px;">'
| |
| .. "[[File:Instrument-icon-" .. family .. ".png|x" .. size .. "px|"
| |
| .. label .. "|link=]]"
| |
| .. "</span></span>"
| |
| end
| |
| | |
| -- {{#invoke:Instruments|family|5-string banjo}} -> banjo
| |
| function p.family( frame )
| |
| return p._family( frame.args[1] )
| |
| end
| |
| | |
| -- {{#invoke:Instruments|badge|5-string banjo|size=18|tuck=1}} | |
| function p.badge( frame )
| |
| local args = frame.args
| |
| return p._badge( args[1], args.size or args[2],
| |
| args.tuck ~= nil and args.tuck ~= "" )
| |
| end
| |
|
| |
|
| return p | | return require( 'pickipedia.instruments' ) |
Documentation for this module may be created at Module:Instruments/doc
-- Which icon stands for an instrument.
--
-- The module itself lives in the repository, at
-- extensions/PickiPediaContent/lua/pickipedia/instruments.lua, and is loaded
-- from there through Scribunto's external library paths. That is deliberate:
-- a module edited here is code that nothing reviews, nothing keeps history
-- for, and nothing can revert. In the repository it gets a pull request, a
-- history, a revert, and tests that run before it ships.
--
-- So change it there, not here. An edit to this page would be overridden by
-- nothing and reviewed by nobody -- it would simply take effect, which is the
-- problem.
--
-- Documentation, including how a name becomes an icon and how to add one:
-- Template:ShowInstrument, and the README beside the Lua.
return require( 'pickipedia.instruments' )