From: Ævar Arnfjörð Bjarmason Date: Tue, 20 Apr 2010 12:55:14 +0000 (+0000) Subject: Ticket #2245: Link from /browse/* pages to the wiki key/value pages X-Git-Tag: live~6947^2~1^2~4 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/8eead8a8707b478b342a6e4c13c4e8b4ef143b98?ds=inline;hp=--cc Ticket #2245: Link from /browse/* pages to the wiki key/value pages --- 8eead8a8707b478b342a6e4c13c4e8b4ef143b98 diff --git a/app/helpers/browse_helper.rb b/app/helpers/browse_helper.rb index aed0c518f..e252e300f 100644 --- a/app/helpers/browse_helper.rb +++ b/app/helpers/browse_helper.rb @@ -15,4 +15,42 @@ module BrowseHelper end return name end + + def wiki_link(type, key, tag) + wiki_data = YAML.load_file("#{RAILS_ROOT}/config/wiki-tag-and-key-description.yml") + my_locale = I18n.locale.to_s + + if type == "key" + ret = key + lookup = key + else + ret = tag + lookup = key + "=" + tag + end + + # Try our native language + has_primary = wiki_data[my_locale][type][lookup] rescue false + if has_primary + ret = wikify(type, key, tag, lookup, wiki_data[my_locale][type][lookup]) + else + # Fall back on English + has_fallback = wiki_data["en"][type][lookup] rescue false + if has_fallback + ret = wikify(type, key, tag, lookup, wiki_data["en"][type][lookup]) + end + end + + return ret + end + + def wikify(type, key, tag, text, wiki) + my_locale = I18n.locale + url = "http://wiki.openstreetmap.org/index.php?title=#{wiki}&uselang=#{my_locale}" + + if type == "key" + return '' + h(text) + '' + else + return '' + h(tag) + '' + end + end end diff --git a/app/views/browse/_tag.html.erb b/app/views/browse/_tag.html.erb index ab5707f9e..4096873da 100644 --- a/app/views/browse/_tag.html.erb +++ b/app/views/browse/_tag.html.erb @@ -1,3 +1,3 @@ - <%= h(tag[0]) %> = <%= linkify(h(tag[1])) %> + <%= wiki_link("key", h(tag[0]), nil) %> = <%= wiki_link("tag", h(tag[0]), auto_link(h(tag[1]))) %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 8699d600c..17bae6c57 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -233,6 +233,9 @@ en: # There is no 'relation' type because it is not represented in OpenLayers tag_details: tags: "Tags:" + wiki_link: + key: "The wiki description page for the {{key}}=* tag" + tag: "The wiki description page for the {{key}}={{value}} tag" way_details: nodes: "Nodes:" part_of: "Part of:" diff --git a/config/wiki-tag-and-key-description.yml b/config/wiki-tag-and-key-description.yml new file mode 100644 index 000000000..832de07a8 --- /dev/null +++ b/config/wiki-tag-and-key-description.yml @@ -0,0 +1,564 @@ +# THIS FILE IS AUTOGENERATED WITH THE script/misc/update-key-and-tag-description-pages-from-wiki +# PROGRAM DO NOT MANUALLY EDIT IT + +--- +cz: + key: + historic: Cz:Key:historic + railway: Cz:Key:railway +de: + key: + abutters: DE:Key:abutters + access: DE:Key:access + addr: DE:Key:addr + aerialway: DE:Key:aerialway + aeroway: DE:Key:aeroway + amenity: DE:Key:amenity + barrier: DE:Key:barrier + basin: DE:Key:basin + bridge: DE:Key:bridge + building: DE:Key:building + comment: DE:Key:comment + crossing: DE:Key:crossing + cycleway: DE:Key:cycleway + denomination: DE:Key:denomination + description: DE:Key:description + disused: DE:Key:disused + drink: DE:Key:drink + embankment: DE:Key:embankment + fixme: DE:Key:fixme + geological: DE:Key:geological + hazmat: DE:Key:hazmat + highway: DE:Key:highway + historic: DE:Key:historic + incline: DE:Key:incline + landuse: DE:Key:landuse + lanes: DE:Key:lanes + layer: DE:Key:layer + leisure: DE:Key:leisure + lit: DE:Key:lit + man_made: DE:Key:man made + maxheight: DE:Key:maxheight + maxspeed: DE:Key:maxspeed + military: DE:Key:military + mtb:scale: DE:Key:mtb:scale + name: DE:Key:name + natural: DE:Key:natural + noexit: DE:Key:noexit + note: DE:Key:note + oneway: DE:Key:oneway + opening_hours: DE:Key:opening hours + operator: DE:Key:operator + osmc:symbol: DE:Key:osmc:symbol + place: DE:Key:place + power: DE:Key:power + power_rating: DE:Key:power rating + railway: DE:Key:railway + route: DE:Key:route + sac_scale: DE:Key:sac scale + service: DE:Key:service + shop: DE:Key:shop + smoothness: DE:Key:smoothness + sport: DE:Key:sport + step_count: DE:Key:step count + surface: DE:Key:surface + tourism: DE:Key:tourism + tracktype: DE:Key:tracktype + trail_visibility: DE:Key:trail visibility + tunnel: DE:Key:tunnel + voltage: DE:Key:voltage + waterway: DE:Key:waterway + wheelchair: DE:Key:wheelchair + wires: DE:Key:wires + wood: DE:Key:wood +en: + key: + Demolished: Key:Demolished + TMC:Direction: Key:TMC:Direction + TMC:LocationCode: Key:TMC:LocationCode + TMC:NextLocationCode: Key:TMC:NextLocationCode + TMC:PrevLocationCode: Key:TMC:PrevLocationCode + abutters: Key:abutters + access: Key:access + addr: Key:addr + addr:conscriptionnumber: Key:addr:conscriptionnumber + addr:provisionalnumber: Key:addr:provisionalnumber + addr:streetnumber: Key:addr:streetnumber + aerialway: Key:aerialway + aeroway: Key:aeroway + amenity: Key:amenity + area: Key:area + atv: Key:atv + barrier: Key:barrier + basin: Key:basin + bicycle: Key:bicycle + boat: Key:boat + border_type: Key:border type + boundary: Key:boundary + bridge: Key:bridge + building: Key:building + bunker_type: Key:bunker type + capacity: Key:capacity + cep: Key:cep + collection_times: Key:collection times + comment: Key:comment + construction: Key:construction + contact: Key:contact + covered: Key:covered + created_by: Key:created by + crossing: Key:crossing + cuisine: Key:cuisine + cutting: Key:cutting + cycleway: Key:cycleway + denomination: Key:denomination + description: Key:description + designation: Key:designation + direction: Key:direction + dispensing: Key:dispensing + disused: Key:disused + drink: Key:drink + easy_overtaking: Key:easy overtaking + ele: Key:ele + electrified: Key:electrified + embankment: Key:embankment + emergency: Key:emergency + end_date: Key:end date + enforcement: Key:enforcement + fee: Key:fee + fence_type: Key:fence type + fenced: Key:fenced + fixme: Key:fixme + foot: Key:foot + gauge: Key:gauge + geological: Key:geological + hazmat: Key:hazmat + healthcare: Key:healthcare + height: Key:height + highway: Key:highway + historic: Key:historic + horse: Key:horse + incline: Key:incline + information: Key:information + internet_access: Key:internet access + is_in: Key:is in + junction: Key:junction + landuse: Key:landuse + lanes: Key:lanes + layer: Key:layer + lcn_ref: Key:lcn ref + leisure: Key:leisure + lit: Key:lit + lit:perceived: Key:lit:perceived + lock: Key:lock + man_made: Key:man made + manhole: Key:manhole + maxairdraft: Key:maxairdraft + maxaxleload: Key:maxaxleload + maxdraught: Key:maxdraught + maxheight: Key:maxheight + maxheight:legal: Key:maxheight:legal + maxheight:marine: Key:maxheight:marine + maxheight:physical: Key:maxheight:physical + maxlength: Key:maxlength + maxspeed: Key:maxspeed + maxstay: Key:maxstay + maxweight: Key:maxweight + maxwidth: Key:maxwidth + military: Key:military + minspeed: Key:minspeed + mooring: Key:mooring + motorcar: Key:motorcar + motorcycle: Key:motorcycle + motorroad: Key:motorroad + mountain_pass: Key:mountain pass + mtb:description: Key:mtb:description + mtb:scale: Key:mtb:scale + name: Key:name + name:cy: Key:name:cy + narrow: Key:narrow + natural: Key:natural + ncn_ref: Key:ncn ref + noexit: Key:noexit + noname: Key:noname + note: Key:note + oneway: Key:oneway + opening_hours: Key:opening hours + operator: Key:operator + osmarender:nameDirection: Key:osmarender:nameDirection + osmarender:render: Key:osmarender:render + osmarender:renderName: Key:osmarender:renderName + osmarender:renderRef: Key:osmarender:renderRef + osmc:symbol: Key:osmc:symbol + overtaking: Key:overtaking + parking: Key:parking + passing_places: Key:passing places + paved:date: Key:paved:date + phone: Key:phone + place: Key:place + population: Key:population + postal_code: Key:postal code + power: Key:power + power_rating: Key:power rating + power_source: Key:power source + proposed: Key:proposed + psv: Key:psv + railway: Key:railway + ramp: Key:ramp + rcn_ref: Key:rcn ref + ref: Key:ref + ref:isil: Key:ref:isil + religion: Key:religion + resource: Key:resource + route: Key:route + sac_scale: Key:sac scale + sagns_id: Key:sagns id + seamark: Key:seamark + seasonal:snowfall:regaintime: Key:seasonal:snowfall:regaintime + service: Key:service + shop: Key:shop + ski: Key:ski + smoothness: Key:smoothness + snowplowing: Key:snowplowing + snowplowing:category: Key:snowplowing:category + source: Key:source + sport: Key:sport + start_date: Key:start date + step_count: Key:step count + stop: Key:stop + sulky: Key:sulky + surface: Key:surface + tactile_paving: Key:tactile paving + toll: Key:toll + tourism: Key:tourism + tracktype: Key:tracktype + traffic:hourly: Key:traffic:hourly + traffic_calming: Key:traffic calming + traffic_sign: Key:traffic sign + trail_visibility: Key:trail visibility + trolley_wire: Key:trolley wire + tunnel: Key:tunnel + type: Key:type + voltage: Key:voltage + waterway: Key:waterway + website: Key:website + wheelchair: Key:wheelchair + width: Key:width + wikipedia: Key:wikipedia + wires: Key:wires + woeid: Key:woeid + wood: Key:wood + zoo: Key:zoo +et: + key: + highway: Et:Key:highway +fi: + key: + amenity: Fi:Key:amenity + bridge: Fi:Key:bridge + crossing: Fi:Key:crossing + description: Fi:Key:description + disused: Fi:Key:disused + ele: Fi:Key:ele + embankment: Fi:Key:embankment + hazmat: Fi:Key:hazmat + lanes: Fi:Key:lanes + layer: Fi:Key:layer + leisure: Fi:Key:leisure + man_made: Fi:Key:man made + manhole: Fi:Key:manhole + narrow: Fi:Key:narrow + natural: Fi:Key:natural + note: Fi:Key:note + operator: Fi:Key:operator + shop: Fi:Key:shop + surface: Fi:Key:surface + tracktype: Fi:Key:tracktype + traffic_calming: Fi:Key:traffic calming + tunnel: Fi:Key:tunnel + waterway: Fi:Key:waterway + wheelchair: Fi:Key:wheelchair + width: Fi:Key:width +fr: + key: + addr: FR:Key:addr + amenity: FR:Key:amenity + barrier: FR:Key:barrier + boundary: FR:Key:boundary + bridge: FR:Key:bridge + building: FR:Key:building + collection_times: FR:Key:collection times + cycleway: FR:Key:cycleway + enforcement: FR:Key:enforcement + highway: FR:Key:highway + landuse: FR:Key:landuse + lanes: FR:Key:lanes + maxweight: FR:Key:maxweight + name: FR:Key:name + noname: FR:Key:noname + opening_hours: FR:Key:opening hours + power: FR:Key:power + sac_scale: FR:Key:sac scale + shop: FR:Key:shop + smoothness: FR:Key:smoothness + waterway: FR:Key:waterway +hr: + key: + tracktype: Hr:Key:tracktype +hu: + key: + aeroway: HU:Key:aeroway + shop: HU:Key:shop + tourism: HU:Key:tourism +it: + key: + aerialway: IT:Key:aerialway + aeroway: IT:Key:aeroway + amenity: IT:Key:amenity + barrier: IT:Key:barrier + boundary: IT:Key:boundary + bridge: IT:Key:bridge + building: IT:Key:building + construction: IT:Key:construction + cutting: IT:Key:cutting + cycleway: IT:Key:cycleway + denomination: IT:Key:denomination + embankment: IT:Key:embankment + enforcement: IT:Key:enforcement + geological: IT:Key:geological + highway: IT:Key:highway + historic: IT:Key:historic + junction: IT:Key:junction + landuse: IT:Key:landuse + leisure: IT:Key:leisure + lock: IT:Key:lock + man_made: IT:Key:man made + military: IT:Key:military + mooring: IT:Key:mooring + name: IT:Key:name + natural: IT:Key:natural + osmc:symbol: IT:Key:osmc:symbol + passing_places: IT:Key:passing places + place: IT:Key:place + power: IT:Key:power + proposed: IT:Key:proposed + railway: IT:Key:railway + ref: IT:Key:ref + religion: IT:Key:religion + route: IT:Key:route + sac_scale: IT:Key:sac scale + service: IT:Key:service + shop: IT:Key:shop + sport: IT:Key:sport + stop: IT:Key:stop + tourism: IT:Key:tourism + tracktype: IT:Key:tracktype + traffic_calming: IT:Key:traffic calming + trail_visibility: IT:Key:trail visibility + tunnel: IT:Key:tunnel + type: IT:Key:type + waterway: IT:Key:waterway + wheelchair: IT:Key:wheelchair +ja: + key: + abutters: Ja:Key:abutters + access: Ja:Key:access + aerialway: Ja:Key:aerialway + aeroway: Ja:Key:aeroway + amenity: Ja:Key:amenity + barrier: Ja:Key:barrier + boundary: Ja:Key:boundary + bridge: Ja:Key:bridge + building: Ja:Key:building + crossing: Ja:Key:crossing + cuisine: Ja:Key:cuisine + cycleway: Ja:Key:cycleway + fixme: Ja:Key:fixme + foot: Ja:Key:foot + highway: Ja:Key:highway + historic: Ja:Key:historic + incline: Ja:Key:incline + information: Ja:Key:information + internet_access: Ja:Key:internet access + landuse: Ja:Key:landuse + leisure: Ja:Key:leisure + man_made: Ja:Key:man made + military: Ja:Key:military + name: Ja:Key:name + natural: Ja:Key:natural + operator: Ja:Key:operator + phone: Ja:Key:phone + power: Ja:Key:power + railway: Ja:Key:railway + ref: Ja:Key:ref + route: Ja:Key:route + shop: Ja:Key:shop + step_count: Ja:Key:step count + surface: Ja:Key:surface + tactile_paving: Ja:Key:tactile paving + tourism: Ja:Key:tourism + tracktype: Ja:Key:tracktype + waterway: Ja:Key:waterway + wheelchair: Ja:Key:wheelchair + wood: Ja:Key:wood +nl: + key: + cycleway: NL:Key:cycleway +no: + key: + fenced: No:Key:fenced + maxheight:marine: No:Key:maxheight:marine +pl: + key: + height: Pl:Key:height + oneway: Pl:Key:oneway +pt-br: + key: + access: Pt-br:Key:access + addr: Pt-br:Key:addr + aeroway: Pt-br:Key:aeroway + amenity: Pt-br:Key:amenity + barrier: Pt-br:Key:barrier + bicycle: Pt-br:Key:bicycle + boat: Pt-br:Key:boat + border_type: Pt-br:Key:border type + boundary: Pt-br:Key:boundary + bridge: Pt-br:Key:bridge + building: Pt-br:Key:building + cep: Pt-br:Key:cep + construction: Pt-br:Key:construction + ele: Pt-br:Key:ele + emergency: Pt-br:Key:emergency + fenced: Pt-br:Key:fenced + foot: Pt-br:Key:foot + hgv: Pt-br:Key:hgv + highway: Pt-br:Key:highway + horse: Pt-br:Key:horse + landuse: Pt-br:Key:landuse + lanes: Pt-br:Key:lanes + leisure: Pt-br:Key:leisure + man_made: Pt-br:Key:man made + maxdraught: Pt-br:Key:maxdraught + maxheight: Pt-br:Key:maxheight + maxheight:legal: Pt-br:Key:maxheight:legal + maxheight:marine: Pt-br:Key:maxheight:marine + maxheight:physical: Pt-br:Key:maxheight:physical + maxspeed: Pt-br:Key:maxspeed + maxweight: Pt-br:Key:maxweight + military: Pt-br:Key:military + motorcar: Pt-br:Key:motorcar + motorcycle: Pt-br:Key:motorcycle + name: Pt-br:Key:name + natural: Pt-br:Key:natural + noname: Pt-br:Key:noname + oneway: Pt-br:Key:oneway + operator: Pt-br:Key:operator + psv: Pt-br:Key:psv + religion: Pt-br:Key:religion + seamark: Pt-br:Key:seamark + shop: Pt-br:Key:shop + ski: Pt-br:Key:ski + source: Pt-br:Key:source + sport: Pt-br:Key:sport + surface: Pt-br:Key:surface + type: Pt-br:Key:type + waterway: Pt-br:Key:waterway +ru: + key: + abutters: RU:Key:abutters + access: RU:Key:access + addr: RU:Key:addr + aerialway: RU:Key:aerialway + aeroway: RU:Key:aeroway + amenity: RU:Key:amenity + area: RU:Key:area + bicycle: RU:Key:bicycle + boat: RU:Key:boat + border_type: RU:Key:border type + boundary: RU:Key:boundary + building: RU:Key:building + bunker_type: RU:Key:bunker type + capacity: RU:Key:capacity + comment: RU:Key:comment + construction: RU:Key:construction + created_by: RU:Key:created by + crossing: RU:Key:crossing + cuisine: RU:Key:cuisine + cutting: RU:Key:cutting + denomination: RU:Key:denomination + description: RU:Key:description + direction: RU:Key:direction + disused: RU:Key:disused + ele: RU:Key:ele + embankment: RU:Key:embankment + fee: RU:Key:fee + fixme: RU:Key:fixme + foot: RU:Key:foot + gauge: RU:Key:gauge + height: RU:Key:height + highway: RU:Key:highway + historic: RU:Key:historic + horse: RU:Key:horse + information: RU:Key:information + internet_access: RU:Key:internet access + junction: RU:Key:junction + landuse: RU:Key:landuse + lanes: RU:Key:lanes + leisure: RU:Key:leisure + man_made: RU:Key:man made + maxheight: RU:Key:maxheight + maxlength: RU:Key:maxlength + maxspeed: RU:Key:maxspeed + maxweight: RU:Key:maxweight + maxwidth: RU:Key:maxwidth + military: RU:Key:military + minspeed: RU:Key:minspeed + name: RU:Key:name + natural: RU:Key:natural + noexit: RU:Key:noexit + note: RU:Key:note + oneway: RU:Key:oneway + opening_hours: RU:Key:opening hours + operator: RU:Key:operator + parking: RU:Key:parking + passing_places: RU:Key:passing places + paved:date: RU:Key:paved:date + phone: RU:Key:phone + place: RU:Key:place + population: RU:Key:population + power: RU:Key:power + railway: RU:Key:railway + ref: RU:Key:ref + religion: RU:Key:religion + route: RU:Key:route + service: RU:Key:service + shop: RU:Key:shop + smoothness: RU:Key:smoothness + source: RU:Key:source + surface: RU:Key:surface + tourism: RU:Key:tourism + tracktype: RU:Key:tracktype + traffic_calming: RU:Key:traffic calming + type: RU:Key:type + waterway: RU:Key:waterway + website: RU:Key:website + width: RU:Key:width + wikipedia: RU:Key:wikipedia + wood: RU:Key:wood +tr: + key: + amenity: Tr:Key:amenity + boundary: Tr:Key:boundary + highway: Tr:Key:highway + historic: Tr:Key:historic + leisure: Tr:Key:leisure + shop: Tr:Key:shop + sport: Tr:Key:sport +uk: + key: + access: Uk:Key:access + highway: Uk:Key:highway + place: Uk:Key:place +zh-hans: + key: + place: Zh-hans:Key:place + diff --git a/script/misc/update-key-and-tag-description-pages-from-wiki b/script/misc/update-key-and-tag-description-pages-from-wiki new file mode 100644 index 000000000..c6550f665 --- /dev/null +++ b/script/misc/update-key-and-tag-description-pages-from-wiki @@ -0,0 +1,149 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use Pod::Usage (); +use Getopt::Long (); + +BEGIN { + eval "require MediaWiki::API; require YAML::XS;" or do { + print "You have to install some modules via CPAN to run this:\n"; + print " sudo cpanp MediaWiki::API YAML::XS\n"; + exit 1; + }; +} + +use MediaWiki::API; +use YAML::XS qw(Dump); +use Test::More 'no_plan'; + +=head1 NAME + +update-key-and-tag-description-pages-from-wiki - Screen-scrape the wiki for key/value wiki description pages + +=head1 SYNOPSIS + + perl script/misc/update-key-and-tag-description-pages-from-wiki config/wiki-tag-and-key-description.yml + +=head1 BUGS + +This will break if there are more than 500 key or value pages. Paging +needs to be implemenented. + +That or using a proper API or something (if it's there) or making a +direct query to the wiki database. + +=cut + +# Get the command-line options +Getopt::Long::Parser->new( + config => [ qw< bundling no_ignore_case no_require_order pass_through > ], +)->getoptions( + 'h|help' => \my $help, +) or help(); + +# On --help +help() if $help; + +help() unless $ARGV[0]; + +# Get a API interface +my $mw = MediaWiki::API->new(); +ok($mw, "Got a MediaWiki API"); +$mw->{config}->{api_url} = 'http://wiki.openstreetmap.org/w/api.php'; + +# All our goodies +my (%feature, %count); + +# This is what you get on: +## http://wiki.openstreetmap.org/w/index.php?search=Template:KeyDescription&fulltext=Search&fulltext=Search +for my $lang ('', map { "${_}:" } qw[ Pt Fi De It HU Cz Fr RU Pl ]) { + ok(1, " Templates for language '$lang'"); + + # Key/value pages + for my $thing (qw(key value)) { + my $Thing = ucfirst $thing; + ok(1, " Getting $thing pages"); + my $cnt = stick_content_in_hash($thing, "Template:${lang}${Thing}Description", \%feature); + ok(1, " Got $cnt $thing pages"); + $count{$thing} += $cnt; + } +} + +ok(1, "Got a total of $count{$_} ${_}s") for qw[ key value ]; + +# Dump to .yml file +open my $out, ">", $ARGV[0] or die "Can't open file '$ARGV[0]' supplied on the command line"; +say $out "# THIS FILE IS AUTOGENERATED WITH THE script/misc/update-key-and-tag-description-pages-from-wiki"; +say $out "# PROGRAM DO NOT MANUALLY EDIT IT"; +say $out ""; +say $out Dump(\%feature); +close $out; + +exit 0; + +sub stick_content_in_hash +{ + my ($key, $title, $hash) = @_; + my $ukey = ucfirst $key; + + my $space_to_underscore = sub { + my $txt = shift; + $txt =~ s/ /_/g; + $txt; + }; + + my $count = 0; + get_embeddedin( + $title, + sub { + my ($links) = @_; + my (@links) = @$links; + ok(1, " ... got " . scalar(@links) . " more links"); + for my $link (@links) { + $count++; + my $title = $link->{title}; + + if ($title =~ /^$ukey:(?.*?)$/) { + # English by default + $hash->{en}->{$key}->{ $space_to_underscore->($+{key_name}) } = $title; + } elsif ($title =~ /^(?[^:]+):$ukey:(?.*?)$/) { + $hash->{lc $+{lang}}->{$key}->{ $space_to_underscore->($+{key_name}) } = $title; + } + } + } + ); + + return $count; +} + +sub get_embeddedin +{ + my ($title, $callback) = @_; + my $articles = $mw->list( + { + action => 'query', + list => 'embeddedin', + eititle => $title, + eifilterredir => 'nonredirects', + # Doesn't work for De:* and anything non-en. Odd. + # einamespace => '0|8', + eilimit => '200', + }, + { + max => '0', + hook => $callback, + skip_encoding => 1, + } + ) || die $mw->{error}->{code} . ': ' . $mw->{error}->{details}; +} + +sub help +{ + my %arg = @_; + + Pod::Usage::pod2usage( + -verbose => $arg{ verbose }, + -exitval => $arg{ exitval } || 0, + ); +}