Pod-Spell-1.17000755001750001750 012477212666 16131 5ustar00xenoterracidexenoterracide000000000000README100644001750001750 1527012477212666 17117 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17NAME Pod::Spell - a formatter for spellchecking Pod VERSION version 1.17 SYNOPSIS use Pod::Spell; Pod::Spell->new->parse_from_file( 'File.pm' ); Pod::Spell->new->parse_from_filehandle( $infile, $outfile ); Also look at podspell % perl -MPod::Spell -e "Pod::Spell->new->parse_from_file(shift)" Thing.pm |spell |fmt ...or instead of piping to spell or ispell, use >temp.txt, and open temp.txt in your word processor for spell-checking. DESCRIPTION Pod::Spell is a Pod formatter whose output is good for spellchecking. Pod::Spell rather like Pod::Text, except that it doesn't put much effort into actual formatting, and it suppresses things that look like Perl symbols or Perl jargon (so that your spellchecking program won't complain about mystery words like "$thing" or "Foo::Bar" or "hashref"). This class provides no new public methods. All methods of interest are inherited from Pod::Parser (which see). The especially interesting ones are parse_from_filehandle (which without arguments takes from STDIN and sends to STDOUT) and parse_from_file. But you can probably just make do with the examples in the synopsis though. This class works by filtering out words that look like Perl or any form of computerese (like "$thing" or "N>7" or "@{$foo}{'bar','baz'}", anything in C<...> or F<...> codes, anything in verbatim paragraphs (code blocks), and anything in the stopword list. The default stopword list for a document starts out from the stopword list defined by Pod::Wordlist, and can be supplemented (on a per-document basis) by having "=for stopwords" / "=for :stopwords" region(s) in a document. METHODS new command interior_sequence textblock verbatim stopwords $self->stopwords->isa('Pod::WordList'); # true ENCODINGS Pod::Parser, which Pod::Spell extends, is extremely naive about character encodings. The parse_from_file method does not apply any PerlIO encoding layer. If your Pod file is encoded in UTF-8, your data will be read incorrectly. You should instead use parse_from_filehandle and manage the input and output layers yourself. binmode($_, ":utf8") for ($infile, $outfile); $my ps = Pod::Spell->new; $ps->parse_from_filehandle( $infile, $outfile ); If your output destination cannot handle UTF-8, you should set your output handle to Latin-1 and tell Pod::Spell to strip out words with wide characters. binmode($infile, ":utf8"); binmode($outfile, ":encoding(latin1)"); $my ps = Pod::Spell->new( no_wide_chars => 1 ); $ps->parse_from_filehandle( $infile, $outfile ); ADDING STOPWORDS You can add stopwords on a per-document basis with "=for stopwords" / "=for :stopwords" regions, like so: =for stopwords plok Pringe zorch snik !qux foo bar baz quux quuux This adds every word in that paragraph after "stopwords" to the stopword list, effective for the rest of the document. In such a list, words are whitespace-separated. (The amount of whitespace doesn't matter, as long as there's no blank lines in the middle of the paragraph.) Plural forms are added automatically using Lingua::EN::Inflect. Words beginning with "!" are deleted from the stopword list -- so "!qux" deletes "qux" from the stopword list, if it was in there in the first place. Note that if a stopword is all-lowercase, then it means that it's okay in any case; but if the word has any capital letters, then it means that it's okay only with that case. So a Wordlist entry of "perl" would permit "perl", "Perl", and (less interestingly) "PERL", "pERL", "PerL", et cetera. However, a Wordlist entry of "Perl" catches only "Perl", not "perl". So if you wanted to make sure you said only "Perl", never "perl", you could add this to the top of your document: =for stopwords !perl Perl Then all instances of the word "Perl" would be weeded out of the Pod::Spell-formatted version of your document, but any instances of the word "perl" would be left in (unless they were in a C<...> or F<...> style). You can have several "=for stopwords" regions in your document. You can even express them like so: =begin stopwords plok Pringe zorch snik !qux foo bar baz quux quuux =end stopwords If you want to use E<...> sequences in a "stopwords" region, you have to use ":stopwords", as here: =for :stopwords virtE ...meaning that you're adding a stopword of "virtù". If you left the ":" out, that would mean you were adding a stopword of "virtE" (with a literal E, a literal <, etc), which will have no effect, since any occurrences of virtE don't look like a normal human-language word anyway, and so would be screened out before the stopword list is consulted anyway. BUGS AND LIMITATIONS finding stopwords defined with =for Pod::Spell makes a single pass over the POD. Stopwords must be added before they show up in the POD. finding the wordlist Pod::Spell uses File::ShareDir::ProjectDistDir if you're getting errors about the wordlist being missing, chances are it's a problem with its heuristics. Set PATH_ISDEV_DEBUG=1 or PATH_FINDDEV_DEBUG=1, or both in your environment for debugging, and then file a bug with File::ShareDir::ProjectDistDir if necessary. HINT If you feed output of Pod::Spell into your word processor and run a spell-check, make sure you're not also running a grammar-check -- because Pod::Spell drops words that it thinks are Perl symbols, jargon, or stopwords, this means you'll have ungrammatical sentences, what with words being missing and all. And you don't need a grammar checker to tell you that. SEE ALSO Pod::Wordlist Pod::Parser podchecker also known as Pod::Checker perlpod, perlpodspec BUGS Please report any bugs or feature requests on the bugtracker website https://github.com/xenoterracide/pod-spell/issues When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. CONTRIBUTORS * David Golden * Kent Fredric * Olivier Mengué AUTHORS * Sean M. Burke * Caleb Cushing COPYRIGHT AND LICENSE This software is Copyright (c) 2015 by Caleb Cushing. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) Changes100644001750001750 512512477212666 17510 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17Revision history Pod-Spell 1.17 2015-03-08 - revert changes in 1.16 they are not compatible with windows GH #18 1.16 2015-02-24 - podspell script: set output encoding from locale CTYPE (DOLMEN) 1.15 2014-02-28 - Convert to strict mode of File::ShareDir::ProjectDistDir (KENTNL) - change to use Path::Tiny->lines_utf8 1.14 2014-02-12 - Discontinue use of File::Slurp, use Path::Tiny->lines instead GH #15 ( Ether ) 1.13 2013-11-02 - fix encoding issues issues in pod for perldoc 1.12 2013-10-17 - improve documentation 1.11 2013-10-17 - fix shebang to /usr/bin/perl for EUMM replacment GH #13 (dolmen) 1.10 2013-09-27 [FEATURES] - added 'no_wide_chars' option to strip words with such characters from the output. This may help spellcheckers that can't cope with UTF-8 [CHANGED] - improved punctuation stripping algorithm for better word isolation (example C<< "hello". >> now is found as "hello") - strips all word that do not have at least one \w character as a spellchecker isn't likely to do anything useful with them [DOCUMENTED] - added recommendations for dealing with character encoding 1.09 2013-09-25 [FIXED] - stopwords with 's are learned without 's to match how they are checked [CHANGED] - leading and trailing punctuation is entirely stripped since the spellchecker won't care anyway. Trailing periods are *not* stripped as they might be abbreviations ("Ph.D."), but such words are checked against the stoplist both with and without trailing periods to account for abbreviations and words at the end of a sentence. 1.08 2013-09-24 [FIXED] - hyphenated word parts are also checked against the stoplist and stripped (dagolden) GH #9 [DOCUMENTED] - noted that stopwords must be added before words appear in Pod 1.07 2013-09-14 - add many words [FEATURES] - Pod::Wordlist is an Object ( dagolden ) - Lingua::EN::Inflect is used to reduce requiring plurals in the list ( dagolden ) - the wordlist is now a sharedir file [DEPRECATED] - accessing %Pod::Wordlist::Wordlist directly 1.06 2013-09-08 - import stopwords from Pod::Wordlist::hanekomu except names 1.05 2013-07-07 - add stopwords 1.04 2013-05-08 - fix tests to work on older perls 1.03 2013-05-08 - update copyright info - require 5.8 (let me know if this is a problem for you) - improve tests - hopefully fix failing test on windows - improve code readability - remove DEBUG for private _is_debug method 1.02 2013-05-07 - convert to dzil and adopt 1.01 2001-10-27 - first release version ( SBURKE ) LICENSE100644001750001750 2152212477212666 17241 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17This software is Copyright (c) 2015 by Caleb Cushing. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. t000755001750001750 012477212666 16315 5ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17utf8.t100644001750001750 301212477212666 17524 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tuse 5.008; # for utf8 use strict; use warnings; use utf8; use Test::More; use Test::Deep; use File::Temp; use Pod::Spell; use Pod::Wordlist; my $builder = Test::More->builder; binmode $builder->output, ":utf8"; binmode $builder->failure_output, ":utf8"; binmode $builder->todo_output, ":utf8"; binmode STDOUT, ":utf8"; my $podfile = File::Temp->new; binmode($podfile, ":utf8"); print $podfile <<'ENDPOD'; =encoding utf8 =for :stopwords virtE résumé =head1 Testing virtE & résumé Our virtE & virtù & résumé for Mengué in 日本 =cut ENDPOD my @cases = ( { label => "wide chars allowed", options => {}, expected => [ qw( Testing Our for Mengué in 日本 ) ], }, { label => "wide chars stripped", options => { no_wide_chars => 1 }, expected => [ qw( Testing Our for Mengué in ) ], }, ); for my $c ( @cases ) { my $textfile = File::Temp->new; binmode $textfile, ":utf8"; # reread from beginning $podfile->seek( 0, 0 ); my $p = new_ok 'Pod::Spell' => [ debug => 1, %{ $c->{options} } ]; $p->parse_from_filehandle( $podfile, $textfile ); # reread from beginning $textfile->seek( 0, 0 ); my $in = do { local $/ = undef, <$textfile> }; my @words = split " ", $in; my @expected = @{ $c->{expected} }; is scalar @words, scalar @expected, "$c->{label}: word count"; cmp_deeply \@words, bag( @expected ), "$c->{label}: words match" or diag "@words"; } done_testing; META.yml100644001750001750 254412477212666 17470 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17--- abstract: 'a formatter for spellchecking Pod' author: - 'Sean M. Burke ' - 'Caleb Cushing ' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' File::Temp: '0' IO::Handle: '0' IPC::Open3: '0' Test::Deep: '0' Test::More: '0' utf8: '0' configure_requires: ExtUtils::MakeMaker: '0' File::ShareDir::Install: '0.06' dynamic_config: 0 generated_by: 'Dist::Zilla version 5.032, CPAN::Meta::Converter version 2.143240' license: artistic_2 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Pod-Spell no_index: file: - perlcritic.rc provides: Pod::Spell: file: lib/Pod/Spell.pm version: '1.17' Pod::Wordlist: file: lib/Pod/Wordlist.pm version: '1.17' requires: Carp: '0' Class::Tiny: '0' File::ShareDir::ProjectDistDir: '1.000' Lingua::EN::Inflect: '0' Pod::Escapes: '0' Pod::Parser: '0' Text::Wrap: '0' base: '0' constant: '0' locale: '0' perl: '5.008' strict: '0' warnings: '0' resources: bugtracker: https://github.com/xenoterracide/pod-spell/issues homepage: https://metacpan.org/dist/Pod-Spell repository: git://github.com/xenoterracide/pod-spell.git version: '1.17' x_contributors: - 'David Golden ' - 'Kent Fredric ' - 'Olivier Mengué ' MANIFEST100644001750001750 126012477212666 17342 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.032. CONTRIBUTING Changes LICENSE MANIFEST META.json META.yml Makefile.PL README bin/podspell lib/Pod/Spell.pm lib/Pod/Wordlist.pm perlcritic.rc share/dist/Pod-Spell/wordlist t/00-compile.t t/00-report-prereqs.dd t/00-report-prereqs.t t/basic.t t/debug.t t/get-stopwords.t t/text-block.t t/utf8.t xt/author/critic.t xt/author/eol.t xt/author/pod-spell.t xt/release/cpan-changes.t xt/release/dist-manifest.t xt/release/meta-json.t xt/release/minimum-version.t xt/release/pod-coverage.t xt/release/pod-linkcheck.t xt/release/pod-syntax.t xt/release/portability.t xt/release/test-version.t xt/release/unused-vars.t debug.t100644001750001750 36112477212666 17710 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tuse strict; use warnings; use Test::More; use Pod::Spell; my $p0 = new_ok 'Pod::Spell' => [ debug => 0 ]; my $p1 = new_ok 'Pod::Spell' => [ debug => 1 ]; ok ! $p0->_is_debug, 'debug unset'; ok $p1->_is_debug, 'debug set'; done_testing; basic.t100644001750001750 230112477212666 17717 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tuse strict; use warnings; use Test::More; use Test::Deep; use File::Temp; use Pod::Spell; use Pod::Wordlist; # realistically we're just checking to make sure the number seems reasonable # and not broken cmp_ok scalar( keys %Pod::Wordlist::Wordlist ), '>=', 1000, 'key count'; my $podfile = File::Temp->new; my $textfile = File::Temp->new; print $podfile "\n=head1 TEST tree's undef\n" . "\n=for stopwords zpaph DDGGSS's myormsp pleumgh bruble-gruble\n" . "\n=for :stopwords !myormsp furble\n\n Glakq\n" . "\nPleumgh bruble-gruble DDGGSS's zpaph's zpaph-kafdkaj-snee myormsp snickh furbles.\n" . "\nFoo::Bar \$a \@b \%c __PACKAGE__->mumble() Foo->{\$bar}\n" . qq[\n"'" Kh.D. ('WinX32'.) L's\n] . qq[\n] ; # reread from beginning $podfile->seek( 0, 0 ); my $p = new_ok 'Pod::Spell' => [ debug => 1 ]; $p->parse_from_filehandle( $podfile, $textfile ); # reread from beginning $textfile->seek( 0, 0 ); my $in = do { local $/ = undef, <$textfile> }; my @words = split " ", $in; my @expected = qw( TEST tree kafdkaj snee myormsp snickh Kh.D. WinX32 s ); is scalar @words, scalar @expected, 'word count'; cmp_deeply \@words, bag( @expected ), 'words match' or diag "@words"; done_testing; META.json100644001750001750 532312477212666 17636 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17{ "abstract" : "a formatter for spellchecking Pod", "author" : [ "Sean M. Burke ", "Caleb Cushing " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 5.032, CPAN::Meta::Converter version 2.143240", "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Pod-Spell", "no_index" : { "file" : [ "perlcritic.rc" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0", "File::ShareDir::Install" : "0.06" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Changes" : "0.19", "Test::EOL" : "0", "Test::More" : "0.88", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Spelling" : "0.12", "Test::Version" : "1" } }, "runtime" : { "requires" : { "Carp" : "0", "Class::Tiny" : "0", "File::ShareDir::ProjectDistDir" : "1.000", "Lingua::EN::Inflect" : "0", "Pod::Escapes" : "0", "Pod::Parser" : "0", "Text::Wrap" : "0", "base" : "0", "constant" : "0", "locale" : "0", "perl" : "5.008", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Test::Deep" : "0", "Test::More" : "0", "utf8" : "0" } } }, "provides" : { "Pod::Spell" : { "file" : "lib/Pod/Spell.pm", "version" : "1.17" }, "Pod::Wordlist" : { "file" : "lib/Pod/Wordlist.pm", "version" : "1.17" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/xenoterracide/pod-spell/issues" }, "homepage" : "https://metacpan.org/dist/Pod-Spell", "repository" : { "type" : "git", "url" : "git://github.com/xenoterracide/pod-spell.git", "web" : "https://github.com/xenoterracide/pod-spell" } }, "version" : "1.17", "x_contributors" : [ "David Golden ", "Kent Fredric ", "Olivier Mengué " ] } Makefile.PL100644001750001750 432512477212666 20170 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.032. use strict; use warnings; use 5.008; use ExtUtils::MakeMaker; use File::ShareDir::Install; $File::ShareDir::Install::INCLUDE_DOTFILES = 1; $File::ShareDir::Install::INCLUDE_DOTDIRS = 1; install_share dist => "share\/dist\/Pod\-Spell"; my %WriteMakefileArgs = ( "ABSTRACT" => "a formatter for spellchecking Pod", "AUTHOR" => "Sean M. Burke , Caleb Cushing ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::ShareDir::Install" => "0.06" }, "DISTNAME" => "Pod-Spell", "EXE_FILES" => [ "bin/podspell" ], "LICENSE" => "artistic_2", "MIN_PERL_VERSION" => "5.008", "NAME" => "Pod::Spell", "PREREQ_PM" => { "Carp" => 0, "Class::Tiny" => 0, "File::ShareDir::ProjectDistDir" => "1.000", "Lingua::EN::Inflect" => 0, "Pod::Escapes" => 0, "Pod::Parser" => 0, "Text::Wrap" => 0, "base" => 0, "constant" => 0, "locale" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "Test::Deep" => 0, "Test::More" => 0, "utf8" => 0 }, "VERSION" => "1.17", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Class::Tiny" => 0, "ExtUtils::MakeMaker" => 0, "File::ShareDir::Install" => "0.06", "File::ShareDir::ProjectDistDir" => "1.000", "File::Spec" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "Lingua::EN::Inflect" => 0, "Pod::Escapes" => 0, "Pod::Parser" => 0, "Test::Deep" => 0, "Test::More" => 0, "Text::Wrap" => 0, "base" => 0, "constant" => 0, "locale" => 0, "strict" => 0, "utf8" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); { package MY; use File::ShareDir::Install qw(postamble); } CONTRIBUTING100644001750001750 2170312477212666 20067 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17Checklist (and a short version for the impatient): Commits: * make sure that you have tests for the bug you are fixing * make sure that the test suite passes after your commit. This distribution is built with Dist::Zilla ensure that running `dzil test` passes. You are responsible for ensuring that generated, hand written and author tests pass. * make commits of logical units * check for unnecessary whitespace with "git diff --check" before committing * do not check in commented out code or unneeded files * the first line of the commit message should be a short description and should skip the full stop * the body should provide a meaningful commit message, which: * uses the imperative, present tense: "change", not "changed" or "changes". * includes motivation for the change, and contrasts its implementation with previous behaviour * if you want your work included in the main repository, add a "Signed-off-by: Your Name " line to the commit message (or just use the option "-s" when committing) to confirm that you agree to the Developer's Certificate of Origin Patch: * if you change, add, or remove any features or make some other user interface change, the associated documentation should be updated as well. * if your name is not writable in ASCII, make sure that you send the patch in the correct encoding. Long version: I started reading over the SubmittingPatches document for git, primarily because I wanted to have a document similar to it for my projects to make sure people understand what they are doing when they write "Signed-off-by" line. But the patch submission requirements are a lot more relaxed here on the technical/contents front, because my projects are thousand times smaller ;-). So here is only the relevant bits. (0) Decide what to base your work on. In general, always base your work on the oldest branch that your change is relevant to. * A bugfix should be based on 'maint' in general. If the bug is not present in 'maint', base it on 'master'. For a bug that's not yet in 'master', find the topic that introduces the regression, and base your work on the tip of the topic. If a 'maint' branch is not present base it on master. * A new feature should be based on 'master' in general. If the new feature depends on a topic that is in 'pu', but not in 'master', base your work on the tip of that topic. * Corrections and enhancements to a topic not yet in 'master' should be based on the tip of that topic. If the topic has not been merged to 'next', it's alright to add a note to squash minor corrections into the series. * In the exceptional case that a new feature depends on several topics not in 'master', start working on 'next' or 'pu' privately and send out patches for discussion. Before the final merge, you may have to wait until some of the dependent topics graduate to 'master', and rebase your work. To find the tip of a topic branch, run "git log --first-parent master..pu" and look for the merge commit. The second parent of this commit is the tip of the topic branch. (1) Make separate commits for logically separate changes. Unless your patch is really trivial, you should not be sending out a patch that was generated between your working tree and your commit head. Instead, always make a commit with complete commit message and generate a series of patches from your repository. It is a good discipline. Describe the technical detail of the change(s). If your description starts to get too long, that's a sign that you probably need to split up your commit to finer grained pieces. That being said, patches which plainly describe the things that help reviewers check the patch, and future maintainers understand the code, are the most beautiful patches. Descriptions that summarise the point in the subject well, and describe the motivation for the change, the approach taken by the change, and if relevant how this differs substantially from the prior version, can be found on Usenet archives back into the late 80's. Consider it like good Netiquette, but for code. Oh, another thing. I am picky about whitespaces. Make sure your changes do not trigger errors with the sample pre-commit hook shipped in templates/hooks--pre-commit. To help ensure this does not happen, run git diff --check on your changes before you commit. (2) Generate your patch using git tools out of your commits. git based diff tools (git, Cogito, and StGIT included) generate unidiff which is the preferred format. You do not have to be afraid to use -M option to "git diff" or "git format-patch", if your patch involves file renames. The receiving end can handle them just fine. Please make sure your patch does not include any extra files which do not belong in a patch submission. Make sure to review your patch after generating it, to ensure accuracy. Before sending out, please make sure it cleanly applies to the "master" branch head. If you are preparing a work based on "next" branch, that is fine, but please mark it as such. (4) Sign your work To improve tracking of who did what, we've borrowed the "sign-off" procedure from the Linux kernel project on patches that are being emailed around. Although this project is a lot smaller it is a good discipline to follow it. The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as a open-source patch. The rules are pretty simple: if you can certify the below: Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. then you just add a line saying Signed-off-by: Random J Developer This line can be automatically added by git if you run the git-commit command with the -s option. Notice that you can place your own Signed-off-by: line when forwarding somebody else's patch with the above rules for D-C-O. Indeed you are encouraged to do so. Also notice that a real name is used in the Signed-off-by: line. Please don't hide your real name. Some people also put extra tags at the end. "Acked-by:" says that the patch was reviewed by the person who is more familiar with the issues and the area the patch attempts to modify. "Tested-by:" says the patch was tested by the person and found to have the desired effect. An ideal patch flow Here is an ideal patch flow for this project the current maintainer suggests to the contributors: 0. You come up with an itch. You code it up. 1. Send it to the bug tracker and cc people who may need to know about the change. The people who may need to know are the ones whose code you are butchering. These people happen to be the ones who are most likely to be knowledgeable enough to help you, but they have no obligation to help you (i.e. you ask for help, don't demand). "git log -p -- $area_you_are_modifying" would help you find out who they are. 2. You get comments and suggestions for improvements. You may even get them in a "on top of your change" patch form. 3. Polish, refine, and re-send to the the people who spend their time to improve your patch. Go back to step (2). 4. A topic branch is created with the patch and is merged to 'next', and cooked further and eventually graduates to 'master'. In any time between the (2)-(3) cycle, the maintainer may pick it up from the list and queue it to 'pu', in order to make it easier for people play with it without having to pick up and apply the patch to their trees themselves. Know the status of your patch after submission * You can use Git itself to find out when your patch is merged in master. 'git pull --rebase' will automatically skip already-applied patches, and will let you know. This works only if you rebase on top of the branch in which your patch has been merged (i.e. it will not tell you if your patch is merged in pu if you rebase on top of master). bin000755001750001750 012477212666 16622 5ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17podspell100755001750001750 217012477212666 20532 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/bin#!/usr/bin/perl use strict; use warnings; use Pod::Spell; our $VERSION = '1.17'; # VERSION if(@ARGV) { # iterate over files, sending to STDOUT foreach my $x (@ARGV) { Pod::Spell->new->parse_from_file($x, '-'); } } else { # take from STDIN, send to STDOUT Pod::Spell->new->parse_from_filehandle(); } # ABSTRACT: pod spell checking command line interface # PODNAME: podspell __END__ =pod =encoding UTF-8 =head1 NAME podspell - pod spell checking command line interface =head1 VERSION version 1.17 =head1 SYNOPSIS % podspell Thing.pm | ispell =head1 BUGS Please report any bugs or feature requests on the bugtracker website https://github.com/xenoterracide/pod-spell/issues When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 AUTHORS =over 4 =item * Sean M. Burke =item * Caleb Cushing =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2015 by Caleb Cushing. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut perlcritic.rc100644001750001750 21312477212666 20654 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17severity = 3 verbose = 9 exclude = RegularExpressions::RequireExtendedFormatting [Subroutines::ProhibitExcessComplexity] max_mccabe = 30 text-block.t100644001750001750 115312477212666 20716 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tuse strict; use warnings; use Test::More; use Test::Deep; use File::Temp; use Pod::Spell; my $podfile = File::Temp->new; my $textfile = File::Temp->new; print $podfile "\n=head1 TEST undef\n" . "\n=begin stopwords\n" . "\nPleumgh zpaph myormsp snickh\n\n" . "\nblah blargh bazh\n\n" . "\n=end stopwords\n" ; # reread from beginning $podfile->seek( 0, 0 ); my $p = new_ok 'Pod::Spell' => [ debug => 1 ]; $p->parse_from_filehandle( $podfile, $textfile ); cmp_deeply [ keys( %{ $p->stopwords->wordlist } ) ], superbagof(qw(Pleumgh zpaph myormsp snickh blah blargh bazh )), 'stopwords added' ; done_testing; 00-compile.t100644001750001750 371312477212666 20513 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tuse 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.051 use Test::More; plan tests => 3 + ($ENV{AUTHOR_TESTING} ? 1 : 0); my @module_files = ( 'Pod/Spell.pm', 'Pod/Wordlist.pm' ); my @scripts = ( 'bin/podspell' ); # no fake home requested my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L my $stderr = IO::Handle->new; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } foreach my $file (@scripts) { SKIP: { open my $fh, '<', $file or warn("Unable to open $file: $!"), next; my $line = <$fh>; close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/; my @flags = $1 ? split(' ', $1) : (); my $stderr = IO::Handle->new; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, @flags, '-c', $file); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$file compiled ok"); # in older perls, -c output is simply the file portion of the path being tested if (@_warnings = grep { !/\bsyntax OK$/ } grep { chomp; $_ ne (File::Spec->splitpath($file))[2] } @_warnings) { warn @_warnings; push @warnings, @_warnings; } } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; author000755001750001750 012477212666 20007 5ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xteol.t100644001750001750 73212477212666 21075 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/authoruse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::EOL 0.17 use Test::More 0.88; use Test::EOL; my @files = ( 'bin/podspell', 'lib/Pod/Spell.pm', 'lib/Pod/Wordlist.pm', 't/00-compile.t', 't/00-report-prereqs.dd', 't/00-report-prereqs.t', 't/basic.t', 't/debug.t', 't/get-stopwords.t', 't/text-block.t', 't/utf8.t' ); eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; done_testing; Pod000755001750001750 012477212666 17342 5ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/libSpell.pm100644001750001750 2663012477212666 21146 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/lib/Podpackage Pod::Spell; use 5.008; use strict; use warnings; our $VERSION = '1.17'; # VERSION use base 'Pod::Parser'; use Pod::Wordlist; use Pod::Escapes ('e2char'); use Text::Wrap ('wrap'); # We don't need a very new version of Text::Wrap, altho they are nicer. $Text::Wrap::huge = 'overflow'; ## no critic ( Variables::ProhibitPackageVars ) use locale; # so our uc/lc works right use Carp; #========================================================================== # # Override some methods # sub new { my ( $class, %args ) = @_; my $new = $class->SUPER::new( %args ); $new->{'region'} = []; $new->{no_wide_chars} = $args{no_wide_chars}; $new->{debug} = $args{debug} || $ENV{PERL_POD_SPELL_DEBUG}; $new->{stopwords} = $args{stopwords} || Pod::Wordlist->new( _is_debug => $new->{debug}, no_wide_chars => $args{no_wide_chars} ); return $new; } sub stopwords { my $self = shift; return $self->{stopwords} } sub verbatim { return ''; } # totally ignore verbatim sections #---------------------------------------------------------------------- sub _is_debug { my $self = shift; return $self->{debug} ? 1 : 0; } #---------------------------------------------------------------------- sub textblock { my ( $self, $paragraph ) = @_; if ( @{ $self->{'region'} } ) { my $last_region ## no critic ( ProhibitAmbiguousNames ) = $self->{'region'}[-1]; if ( $last_region eq 'stopwords' ) { $self->stopwords->learn_stopwords($paragraph); return; } elsif ( $last_region eq ':stopwords' ) { $self->stopwords->learn_stopwords( $self->interpolate($paragraph) ); # I guess that'd work. return; } elsif ( $last_region !~ m/^:/s ) { printf "Ignoring a textblock because inside a %s region.\n", $self->{'region'}[-1] if $self->_is_debug; return; } # else fall thru, as with a :footnote region or something... } $self->_treat_words( $self->interpolate($paragraph) ); return; } sub command { ## no critic ( ArgUnpacking) # why do I have to shift these? my ( $self, $command, $text ) = ( shift, shift, @_ ); return if $command eq 'pod'; if ( $command eq 'begin' ) { ## no critic ( ControlStructures::ProhibitCascadingIfElse ) my $region_name; #print "BEGIN <$_[0]>\n"; if ( $text =~ m/^\s*(\S+)/s ) { $region_name = $1; } else { $region_name = 'WHATNAME'; } print "~~~~ Beginning region \"$region_name\" ~~~~\n" if $self->_is_debug; push @{ $self->{'region'} }, $region_name; } elsif ( $command eq 'end' ) { pop @{ $self->{'region'} }; # doesn't bother to check } elsif ( $command eq 'for' ) { if ( $text =~ s/^\s*(\:?)stopwords\s*(.*)//s ) { my $para = $2; $para = $self->interpolate($para) if $1; print "Stopword para: <$2>\n" if $self->_is_debug; $self->stopwords->learn_stopwords($para); } } elsif ( @{ $self->{'region'} } ) { # TODO: accept POD formatting # ignore } elsif ($command eq 'head1' or $command eq 'head2' or $command eq 'head2' or $command eq 'head3' or $command eq 'item' ) { my $out_fh = $self->output_handle(); print $out_fh "\n"; $self->_treat_words( $self->interpolate(shift) ); #print $out_fh "\n"; } return; } #-------------------------------------------------------------------------- sub interior_sequence { ## no critic ( Subroutines::RequireFinalReturn ) my ( $self, $command, $seq_arg ) = @_; return '' if $command eq 'X' or $command eq 'Z'; # Expand escapes into the actual character now, carping if invalid. if ( $command eq 'E' ) { my $it = e2char( $seq_arg ); if ( defined $it ) { return $it; } else { carp "Unknown escape: E<$seq_arg>"; return "E<$seq_arg>"; } } # For all the other sequences, empty content produces no output. return if $seq_arg eq ''; if ( $command eq 'B' or $command eq 'I' or $command eq 'S' ) { $seq_arg; } elsif ( $command eq 'C' or $command eq 'F' ) { # don't lose word-boundaries my $out = ''; $out .= ' ' if s/^\s+//s; my $append; $append = 1 if s/\s+$//s; $out .= '_' if length $seq_arg; # which, if joined to another word, will set off the Perl-token alarm $out .= ' ' if $append; $out; } elsif ( $command eq 'L' ) { return $1 if m/^([^|]+)\|/s; ''; } else { carp "Unknown sequence $command<$seq_arg>"; } } #-------------------------------------------------------------------------- sub _treat_words { my ($self, $text) = @_; my $out = $self->stopwords->strip_stopwords( $text ); if ( length $out ) { my $out_fh = $self->output_handle(); print $out_fh wrap( '', '', $out ), "\n\n"; } return; } #-------------------------------------------------------------------------- 1; # ABSTRACT: a formatter for spellchecking Pod __END__ =pod =encoding UTF-8 =head1 NAME Pod::Spell - a formatter for spellchecking Pod =head1 VERSION version 1.17 =head1 SYNOPSIS use Pod::Spell; Pod::Spell->new->parse_from_file( 'File.pm' ); Pod::Spell->new->parse_from_filehandle( $infile, $outfile ); Also look at L % perl -MPod::Spell -e "Pod::Spell->new->parse_from_file(shift)" Thing.pm |spell |fmt ...or instead of piping to spell or C, use Ctemp.txt>, and open F in your word processor for spell-checking. =head1 DESCRIPTION Pod::Spell is a Pod formatter whose output is good for spellchecking. Pod::Spell rather like L, except that it doesn't put much effort into actual formatting, and it suppresses things that look like Perl symbols or Perl jargon (so that your spellchecking program won't complain about mystery words like "C<$thing>" or "C" or "hashref"). This class provides no new public methods. All methods of interest are inherited from L (which see). The especially interesting ones are C (which without arguments takes from STDIN and sends to STDOUT) and C. But you can probably just make do with the examples in the synopsis though. This class works by filtering out words that look like Perl or any form of computerese (like "C<$thing>" or "C7>" or "C<@{$foo}{'bar','baz'}>", anything in CE...E or FE...E codes, anything in verbatim paragraphs (code blocks), and anything in the stopword list. The default stopword list for a document starts out from the stopword list defined by L, and can be supplemented (on a per-document basis) by having C<"=for stopwords"> / C<"=for :stopwords"> region(s) in a document. =head1 METHODS =head2 new =head2 command =head2 interior_sequence =head2 textblock =head2 verbatim =head2 stopwords $self->stopwords->isa('Pod::WordList'); # true =for :stopwords virtE =head1 ENCODINGS Pod::Parser, which Pod::Spell extends, is extremely naive about character encodings. The C method does not apply any PerlIO encoding layer. If your Pod file is encoded in UTF-8, your data will be read incorrectly. You should instead use C and manage the input and output layers yourself. binmode($_, ":utf8") for ($infile, $outfile); $my ps = Pod::Spell->new; $ps->parse_from_filehandle( $infile, $outfile ); If your output destination cannot handle UTF-8, you should set your output handle to Latin-1 and tell Pod::Spell to strip out words with wide characters. binmode($infile, ":utf8"); binmode($outfile, ":encoding(latin1)"); $my ps = Pod::Spell->new( no_wide_chars => 1 ); $ps->parse_from_filehandle( $infile, $outfile ); =head1 ADDING STOPWORDS You can add stopwords on a per-document basis with C<"=for stopwords"> / C<"=for :stopwords"> regions, like so: =for stopwords plok Pringe zorch snik !qux foo bar baz quux quuux This adds every word in that paragraph after "stopwords" to the stopword list, effective for the rest of the document. In such a list, words are whitespace-separated. (The amount of whitespace doesn't matter, as long as there's no blank lines in the middle of the paragraph.) Plural forms are added automatically using L. Words beginning with "!" are I from the stopword list -- so "!qux" deletes "qux" from the stopword list, if it was in there in the first place. Note that if a stopword is all-lowercase, then it means that it's okay in I case; but if the word has any capital letters, then it means that it's okay I with I case. So a Wordlist entry of "perl" would permit "perl", "Perl", and (less interestingly) "PERL", "pERL", "PerL", et cetera. However, a Wordlist entry of "Perl" catches only "Perl", not "perl". So if you wanted to make sure you said only "Perl", never "perl", you could add this to the top of your document: =for stopwords !perl Perl Then all instances of the word "Perl" would be weeded out of the Pod::Spell-formatted version of your document, but any instances of the word "perl" would be left in (unless they were in a CE...> or FE...> style). You can have several "=for stopwords" regions in your document. You can even express them like so: =begin stopwords plok Pringe zorch snik !qux foo bar baz quux quuux =end stopwords If you want to use EE...> sequences in a "stopwords" region, you have to use ":stopwords", as here: =for :stopwords virtE ...meaning that you're adding a stopword of "virtE". If you left the ":" out, that would mean you were adding a stopword of "virtEEugrave>" (with a literal E, a literal <, etc), which will have no effect, since any occurrences of virtEEugrave> don't look like a normal human-language word anyway, and so would be screened out before the stopword list is consulted anyway. =head1 BUGS AND LIMITATIONS =head2 finding stopwords defined with C<=for> Pod::Spell makes a single pass over the POD. Stopwords must be added B they show up in the POD. =head2 finding the wordlist Pod::Spell uses L if you're getting errors about the wordlist being missing, chances are it's a problem with its heuristics. Set C or C, or both in your environment for debugging, and then file a bug with L if necessary. =head1 HINT If you feed output of Pod::Spell into your word processor and run a spell-check, make sure you're I also running a grammar-check -- because Pod::Spell drops words that it thinks are Perl symbols, jargon, or stopwords, this means you'll have ungrammatical sentences, what with words being missing and all. And you don't need a grammar checker to tell you that. =head1 SEE ALSO L L L also known as L L, L =head1 BUGS Please report any bugs or feature requests on the bugtracker website https://github.com/xenoterracide/pod-spell/issues When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 CONTRIBUTORS =for stopwords David Golden Kent Fredric Olivier Mengué =over 4 =item * David Golden =item * Kent Fredric =item * Olivier Mengué =back =head1 AUTHORS =over 4 =item * Sean M. Burke =item * Caleb Cushing =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2015 by Caleb Cushing. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut get-stopwords.t100644001750001750 67112477212666 21447 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tuse strict; use warnings; use Test::More; use Test::Deep; use Pod::Wordlist; my $p = new_ok 'Pod::Wordlist'; $p->learn_stopwords( 'foo bar baz' ); cmp_deeply [ keys( %{ $p->wordlist } ) ], superbagof(qw(foo bar baz )), 'stopwords added' ; $p->learn_stopwords( '!foo' ); cmp_deeply [ keys( %{ $p->wordlist } ) ], superbagof(qw( bar baz )), 'stopwords still exist'; ok ! exists $p->wordlist->{foo}, 'foo was removed'; done_testing; critic.t100644001750001750 43512477212666 21573 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/author#!perl use strict; use warnings; use Test::More; use English qw(-no_match_vars); eval "use Test::Perl::Critic"; plan skip_all => 'Test::Perl::Critic required to criticise code' if $@; Test::Perl::Critic->import( -profile => "perlcritic.rc" ) if -e "perlcritic.rc"; all_critic_ok(); Wordlist.pm100644001750001750 1435212477212666 21674 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/lib/Podpackage Pod::Wordlist; use strict; use warnings; use Lingua::EN::Inflect 'PL'; use File::ShareDir::ProjectDistDir 1.000 dist_file => defaults => { pathtiny => 1 , strict => 1 }; use Class::Tiny { wordlist => \&_copy_wordlist, _is_debug => 0, no_wide_chars => 0, }; use constant MAXWORDLENGTH => 50; ## no critic ( ProhibitConstantPragma ) our $VERSION = '1.17'; # VERSION our %Wordlist; ## no critic ( Variables::ProhibitPackageVars ) sub _copy_wordlist { return { %Wordlist } } foreach ( dist_file('Pod-Spell', 'wordlist')->lines_utf8({ chomp => 1 })) { $Wordlist{$_} = 1; $Wordlist{PL($_)} = 1; } sub learn_stopwords { my ( $self, $text ) = @_; my $stopwords = $self->wordlist; while ( $text =~ m<(\S+)>g ) { my $word = $1; if ( $word =~ m/^!(.+)/s ) { # "!word" deletes from the stopword list my $negation = $1; # different $1 from above delete $stopwords->{$negation}; delete $stopwords->{PL($negation)}; print "Unlearning stopword <$negation>\n" if $self->_is_debug; } else { $word =~ s{'s$}{}; # we strip 's when checking so strip here, too $stopwords->{$word} = 1; $stopwords->{PL($word)} = 1; print "Learning stopword <$word>\n" if $self->_is_debug; } } return; } sub is_stopword { my ($self, $word) = @_; my $stopwords = $self->wordlist; if ( exists $stopwords->{$word} or exists $stopwords->{ lc $word } ) { print " Rejecting <$word>\n" if $self->_is_debug; return 1; } return; } sub strip_stopwords { my ($self, $text) = @_; # Count the things in $text print "Content: <", $text, ">\n" if $self->_is_debug; my @words = grep { length($_) < MAXWORDLENGTH } split " ", $text; for ( @words ) { print "Parsing word: <$_>\n" if $self->_is_debug; # some spellcheckers can't cope with anything but Latin1 $_ = '' if $self->no_wide_chars && /[^\x00-\xFF]/; # strip leading punctuation s/^[\(\[\{\'\"\:\;\,\?\!\.]+//; # keep everything up to trailing punctuation, not counting # periods (for abbreviations like "Ph.D."), single-quotes # (for contractions like "don't") or colons (for package # names like "Foo::Bar") s/^([^\)\]\}\"\;\,\?\!]+).*$/$1/; # strip trailing single-quote, periods or colons; after this # we have a word that could have internal periods or quotes s/[\.\'\:]+$//; # strip possessive s/'s$//i; # zero out variable names or things with internal symbols, # since those are probably code expressions outside a C<> my $is_sigil = /^[\&\%\$\@\:\<\*\\\_]/; my $is_strange = /[\%\^\&\#\$\@\_\<\>\(\)\[\]\{\}\\\*\:\+\/\=\|\`\~]/; $_ = '' if $is_sigil || $is_strange; # stop if there are no "word" characters left; if it's just # punctuation that we didn't happen to strip or it's weird glyphs, # the spellchecker won't do any good anyway next unless /\w/; print " Checking as <$_>\n" if $self->_is_debug; # replace it with any stopword or stopword parts stripped $_ = $self->_strip_a_word($_); print " Keeping as <$_>\n" if $_ && $self->_is_debug; } return join(" ", grep { length } @words ); } sub _strip_a_word { my ($self, $word) = @_; my $remainder; # internal period could be abbreviations, so check with # trailing period restored and drop or keep on that basis if ( /\./ ) { my $abbr = "$word."; $remainder = $self->is_stopword($abbr) ? '' : $abbr; } # try word as-is, including possible hyphenation vs stoplist elsif ($self->is_stopword($word) ) { $remainder = ''; } # check individual parts of hyphenated word, keep whatever isn't a # stopword as individual words elsif ( $word =~ /-/ ) { my @keep; for my $part ( split /-/, $word ) { push @keep, $part if ! $self->is_stopword( $part ); } $remainder = join(" ", @keep) if @keep; } # otherwise, we just keep it else { $remainder = $word; } return $remainder; } 1; # ABSTRACT: English words that come up in Perl documentation __END__ =pod =encoding UTF-8 =head1 NAME Pod::Wordlist - English words that come up in Perl documentation =head1 VERSION version 1.17 =head1 DESCRIPTION Pod::Wordlist is used by L, providing a set of words that are English jargon words that come up in Perl documentation, but which are not to be found in general English lexicons. (For example: autovivify, backreference, chroot, stringify, wantarray.) You can also use this wordlist with your word processor by just pasting C's content into your wordprocessor, deleting the leading Perl code so that only the wordlist remains, and then spellchecking this resulting list and adding every word in it to your private lexicon. =head1 ATTRIBUTES =head2 wordlist ref $self->wordlist eq 'HASH'; # true This is the instance of the wordlist =head2 no_wide_chars If true, words with characters outside the Latin-1 range C<0x00> to C<0xFF> will be stripped like stopwords. =head1 METHODS =head2 learn_stopwords $wordlist->learn_stopwords( $text ); Modifies the stopword list based on a text block. See the rules for for details. =head2 is_stopword if ( $wordlist->is_stopword( $word ) ) { ... } Returns true if the word is found in the stopword list. =head2 strip_stopwords my $out = $wordlist->strip_stopwords( $text ); Returns a string with space separated words from the original text with stopwords removed. =head1 WORDLIST Note that the scope of this file is only English, specifically American English. (But you may find in useful to incorporate into your own lexicons, even if they are for other dialects/languages.) remove any q{'s} before adding to the list. The list should be sorted and uniqued. The following will work (with GNU Coreutils ). sort share/wordlist -u > /tmp/sorted && mv /tmp/sorted share/wordlist =head1 BUGS Please report any bugs or feature requests on the bugtracker website https://github.com/xenoterracide/pod-spell/issues When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 AUTHORS =over 4 =item * Sean M. Burke =item * Caleb Cushing =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2015 by Caleb Cushing. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut 00-report-prereqs.t100644001750001750 1273112477212666 22075 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/t#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.020 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do 't/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; if ( $source && $HAS_CPAN_META ) { if ( my $meta = eval { CPAN::Meta->load_file($source) } ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } } else { $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( @dep_errors ) { diag join("\n", "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n", "The following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: pod-spell.t100644001750001750 61412477212666 22214 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/authoruse strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006008 use Test::Spelling 0.12; use Pod::Wordlist; add_stopwords(); all_pod_files_spelling_ok( qw( bin lib ) ); __DATA__ podspell qux virt textblock Sean Burke sburke Caleb Cushing xenoterracide David Golden dagolden Kent Fredric kentfredric Olivier Mengué dolmen lib Pod Spell Wordlist 00-report-prereqs.dd100644001750001750 476012477212666 22204 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/tdo { my $x = { 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::ShareDir::Install' => '0.06' } }, 'develop' => { 'requires' => { 'Pod::Coverage::TrustPod' => '0', 'Test::CPAN::Changes' => '0.19', 'Test::EOL' => '0', 'Test::More' => '0.88', 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.08', 'Test::Spelling' => '0.12', 'Test::Version' => '1' } }, 'runtime' => { 'requires' => { 'Carp' => '0', 'Class::Tiny' => '0', 'File::ShareDir::ProjectDistDir' => '1.000', 'Lingua::EN::Inflect' => '0', 'Pod::Escapes' => '0', 'Pod::Parser' => '0', 'Text::Wrap' => '0', 'base' => '0', 'constant' => '0', 'locale' => '0', 'perl' => '5.008', 'strict' => '0', 'warnings' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'File::Temp' => '0', 'IO::Handle' => '0', 'IPC::Open3' => '0', 'Test::Deep' => '0', 'Test::More' => '0', 'utf8' => '0' } } }; $x; }release000755001750001750 012477212666 20125 5ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xtmeta-json.t100644001750001750 23312477212666 22325 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use Test::More; eval 'use Test::CPAN::Meta::JSON'; plan skip_all => 'Test::CPAN::Meta::JSON required for testing META.json' if $@; meta_json_ok(); pod-syntax.t100644001750001750 22012477212666 22532 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use Test::More; use Test::Pod 1.41; all_pod_files_ok(); portability.t100644001750001750 27712477212666 23002 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use strict; use warnings; use Test::More; eval 'use Test::Portability::Files'; plan skip_all => 'Test::Portability::Files required for testing portability' if $@; run_tests(); unused-vars.t100644001750001750 36212477212666 22707 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use Test::More 0.96 tests => 1; eval { require Test::Vars }; SKIP: { skip 1 => 'Test::Vars required for testing for unused vars' if $@; Test::Vars->import; subtest 'unused vars' => sub { all_vars_ok(); }; }; pod-coverage.t100644001750001750 33412477212666 23005 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. use Test::Pod::Coverage 1.08; use Pod::Coverage::TrustPod; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); test-version.t100644001750001750 60412477212666 23074 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/releaseuse strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::Version 0.003001 use Test::Version; my @imports = ( 'version_all_ok' ); my $params = { is_strict => 0, has_version => 1, }; push @imports, $params if version->parse( $Test::Version::VERSION ) >= version->parse('1.002'); Test::Version->import(@imports); version_all_ok; done_testing; cpan-changes.t100644001750001750 26312477212666 22762 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use strict; use warnings; use Test::More 0.96 tests => 2; use_ok('Test::CPAN::Changes'); subtest 'changes_ok' => sub { changes_file_ok('Changes'); }; done_testing(); dist-manifest.t100644001750001750 23012477212666 23174 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use Test::More; eval "use Test::DistManifest"; plan skip_all => "Test::DistManifest required for testing the manifest" if $@; manifest_ok(); pod-linkcheck.t100644001750001750 53712477212666 23152 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use strict; use warnings; use Test::More; foreach my $env_skip ( qw( SKIP_POD_LINKCHECK ) ){ plan skip_all => "\$ENV{$env_skip} is set, skipping" if $ENV{$env_skip}; } eval "use Test::Pod::LinkCheck"; if ( $@ ) { plan skip_all => 'Test::Pod::LinkCheck required for testing POD'; } else { Test::Pod::LinkCheck->new->all_pod_ok; } minimum-version.t100644001750001750 27012477212666 23567 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/xt/release#!perl use Test::More; eval "use Test::MinimumVersion"; plan skip_all => "Test::MinimumVersion required for testing minimum versions" if $@; all_minimum_version_from_metayml_ok(); Pod-Spell000755001750001750 012477212666 21716 5ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/share/distwordlist100644001750001750 2412212477212666 23671 0ustar00xenoterracidexenoterracide000000000000Pod-Spell-1.17/share/dist/Pod-SpellAas absolutize absolutized absolutizing accessor ACLs acos ActivePerl ActiveState adaptee addset administrativa AES afterwards aggregator Albery aliased aliasing alloc alphabetic alphanumeric AMD Amiga AmigaOS Aminet analysis AnyEvent AoH AOP API APIs arcana arg arrayref asctime asin AspectJ associativity atan atexit atime atof atoi atol authenticator autocroak autoflush autoflushing autogenerate autogenerated autoincrement autoload autoloadable autoloaded AutoLoader autoloading automagically autoprocess autoquoting autosplit autouse autovivification autovivified autovivify autovivifying awk Babelfish backend backgrounded backgrounding backlink backquote backquoting backreference backreferencing backslashed backslashing backtick backtrace backwhack backwhacking bareword basename bcrypt behaviour benchmarked benchmarking bidirectional binmode bistable bitfield bitstring bitwise blead bleadperl blib blockdenting blog bool boolean breakpoint BSCINABTE bsearch bugfix bugfixing bugtracker buildable builtin Bunce byacc bytecode byteorder byteperl bytestream CAcert callback callee calloc CamelCase canonicalize canonpath capturable CAs catdir catfile ccflags cd centric cetera CGIs changelog charset chdir checksumming chmod chomp chown chr chroot chrooted chunked ciphertext CISC classname clearerr CLI clickable closebrace closedir cmp codepage codepoint coderef coercion commifies compilable composable computerese config configurability configurator coprocess copyable coredump Coreutils Coro coroutine cos cosh cpan CPANPLUS CPAN.pm cpantester cperl cpp creat crlf cron crosscutting cruft cryptographically csh css ctermid ctime curdir curly cuserid cwd cyclicity cygwin daemonization datagram dataset datastream datatype datestamp datetime DBI dbmclose dbmopen deallocate deallocated deallocation Debian debugger decompiler decrypting delset delurk denormalized deparse dequeue deref dereference dereferenced dereferencer dereferencing dereffing deregistered deserialization deserialize deserialized deserializing destructor die'ing diff difftime dirhandle distname Django djgpp dmake DNS Dominus don'ts dosish dotfile downcase drivename DSL DTDs DWIM DWIMs DynaLoader dzil egrep egroup EINTR elsif emacs emptyset encipherment encoding endeavour endgrent endhostent endian endnetent endprotoent endpwent endservent enqueue enqueued enum eof EPP eq errno et euid eval evalled execl execle execlp executable execv execve execvp EXEs fabs FAQs fatalize fatalized fatpacking fclose fcntl fdopen feof ferror fflush fgetc fgetpos fgets Fibonacci fifo fileglob filehandle filemode filename fileno filesize filespec filesystem filetest fillset Firefox FirePHP FIXME fixpath flatfile fmod fmt followup fopen foreach foregrounded formatter formfeed formline fpathconf fprintf fputc fputs fread FreeBSD FreezeThaw freopen Freshmeat Friedl frontend fscanf fseek fsetpos fstat ftell ftok fu func fwrite gcc gcos getall getattr getc getcc getcflag getchar getcwd getegid getenv geteuid getgid getgrent getgrgid getgrnam getgroups gethostbyaddr gethostbyname gethostent getiflag getispeed getlflag getlogin getncnt getnetbyaddr getnetbyname getnetent getoflag Getopts getospeed getpeername getpgrp getpid getppid getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname gettimeofday getuid getval getzcnt gid GIFs Gisle github glibc global globbed globbing globref gmtime GNU Google goto gotos grandfathered GraphViz grep grepped grepping groff gt guid gunzip gvim gz gzip gzipped hacky hardcoded hardcoding hashref Hietaniemi HMAC HMACs homepage honoured hostname hostonly htgroup htmldir htmlroot htpasswd HTTP httpd httponly https Hurd iconv idempotency identifier IDs IETF Ilya implementor indices inf inferencing infile ini init initializer inline inlined inlining inode inplace installable int interconversion interconverted interoperability interprocess invocant ioctl IP IPs IPv IPv4 IPv6 IRC isa isalnum isalpha isatty iscntrl isdigit isgraph ish islower ismember ISP isprint ISPs ispunct isspace isupper isxdigit iteratively iterator iTerm japanese japh Jarkko javascript Joseki jpg json Kerberos ksh kwalitee lastkey LaTeX lc lcfirst ldexp ldiv Lenzo lex lexer lexical lexically lexing lexperl libdes libnet libwww linearized linux localeconv localhost localtime locator lockf logfile logical login longjmp lookahead lookbehind lookup lossy lseek lstat lt Lukka lvalue lwp MachTen MacOS MacPerl MACs mailx makefile MakeMaker malloc manpage Markdown marshalling matlab maxima mblen mbstowcs mbtowc memcached memchr memcmp memcpy memmove memoization memoize memoized memoizing memset Mersenne metacharacter metaclasses metaconfig metadata metainformation metaquoting Mexico microtuning middleware miniperl miscompiled misconfiguration misconfigured mixin mkdir mkdn mkdtemp mkfifo mkstemp mktemp mktime modf modulino MongoDB monkeypatch monkeypatching monospaced mortalize mortalized mountpoint Mozilla msgctl msgget MSWin mtime multi multibyte multicast multicharacter multihomed multiline multiprocess multithreadable multi-value multivalued multi-valued multiwindow munge munger munging munition mutator mutex mv MVC MYMETA mysql namespace NaN Nandor NaNs Napster nawk ncftp nd ndbm ne nestable New newline NFS nmake nonabortive nonblocking nonthreaded noop nosuid nroff numeric numify nvi nybble obsoleted occurence of offsetof ok OO OOP op opcode openbrace OpenBSD opendir OpenSSH opnumber Opscode Orcish ord orientedness Orwant OSX outdent outfile overloadable overpackage overwriteable PadWalker parameterizable parameterized parametric PARC paren parser passphrase passwd patchlevel pathconf pathname peeraddr peerhost peerport perl perlaix perlamiga perlbook perlboot perlbootc perlbot perlbug perlcc perlclib perlcompile perlcritic perlcygwin perldata perldbmfilter perldebguts perldebtut perldelta perldiag perldoc perldos perldsc perlebcdic perlepoc perlfaq perlfilter perlfork perlform perlhack perlhist perlhpux perlintern perlio perliotut perlipc Perlis Perlish perllexwarn perllol perlmachten perlmacos perlmain perlmodinstall Perlmonks perlmpeix perlnewmod perlnumber perlobj perlopentut perlpod perlport perlref perlreftut perlrequick perlretut perlrun perlsh perlsolaris perlstyle perlsyn perlthrtut perltoc perltodo perltootc perltrap perlunicode perlutil perlvos perlxs perlxstut perror pessimal pessimize petabyte Ph.D. phash PHP pid pkunzip placeholder Plack pluggable plugin PluginBundle podchecker podified podlator PodParser podpath podroot podselect pointcut polymorphic polymorphing POSIX postamble postorder pow pragma pragmata pre preallocate preallocated preallocation prebuilt precompiled precompute precomputed predeclaration predeclare predeclared prepend prepended prepending preprocessed prereq printf PRNG PRNGs processable procfs programmatically prototyped proxied Prymmer pseudoclass PSGI Psion ptr pumpking putc putchar qr qsort quartile Quicksort quotemeta qx rand RDBM RDBMs RDBMS rdo readdir readline readlink README README.posix?bc readpipe real realloc realtime recomputation recompute recomputing recurse recv redeclaration Redhat redirection redispatch redistributable ref regex regexp reimplement rekeying RemotePort renderable renice reparse repo representable resample resampling resending resolver reswap rethrow rethrown reusability reval rewinddir RFCs rindex RISC rmdir roadmap roff rootdir rsh rsync runnable runtime rvalue rxvt san sbrace%s scalability scanf Schwartzian scoping scp searchable sed seekable seekdir segfault SelfLoading semctl semget semop sendmail Sereal serializer setall setattr setcc setcflag setenv setgid setgrent sethostent setiflag setispeed setjmp setlflag setlocale setlogsock setnetent setoflag setospeed setpgid setpriority setprotoent setpwent setregid setreuid setservent setsid setuid setval sfio sh SHA shipit shmctl shmget shmread shmwrite sigaction sighandler sigil siglongjmp sigpending sigprocmask sigsetjmp sigsuspend sigtrap SimpleDB sinh sizeof SMTP snd sockaddr sockdomain sockhost sockport socktype soundex SourceForge spam specifier spellcheck spellchecking Spiffy sprintf SQL sqlite sqrt srand sscanf SSL startup statefulness statfs static stderr stdin stdio stdios stdout stopword storable storage strcat strchr strcmp strcoll strcpy strcspn strerror strftime stringification stringified stringify stringifying stringwise strlen strncat strncmp strncpy strpbrk strrchr strspn strstr strtod strtok strtol strtoul struct strxfrm stty subclass subclassed subclassing subdir subdirectory subexpression submatch subnode subobject subpattern subprocess subscriptable substr substring subtree subtype subtyped sudo suidperl superclass superuser svk SVs Sx symlink symlinked sysadmin syscall sysconf syslog sysopen sysread sysseek syswrite taintedness tanh tarball tcdrain tcflow tcflush tcgetattr tcgetpgrp tcl tcsendbreak tcsetpgrp tcsh teardown telldir tempdir tempfile templating tempnam Tenon termcap termios TeX textarea threadedness throwable timegm timelocal timestamp timezone TIMTOWTDI TIMTOWTDIBSCINABTE titlecase Tk tmpfile tmpnam tokenize tokenizer tolower toolchain Torkington toupper tr transcoding tridirectional trn tty ttyname Tuomas tuple Turoff twip txt typechecking typedefs typeglob typemap tzname tzset uc ucfirst uid ulimit umask uname unbackslashed unblessed unbuffer unbuffered unbuffering unbundled uncastable unconfigured uncuddled undef undefine undefining undenting undiagnosed undump unencrypted unescape unescaped unescaping unexpand ungetc unhandled Unicode unimport unindented uninitialized uniqued University unix Unixish unlink unlinked unlinking unmaintainable unmaintained unmangled unmemoized unmorph unmounting unordered unparsable unportable unprototyped unreferenced unshift unshifted unsignedness unsubscripted untaint untainting untrap untrappable untrapped untrusted unzipper upcase updir upgradability urandom uri URI.pm url userinfo username utc utf utime uuid val varglob variadic vec versa vfprintf vgrind vim vprintf Vromans vsprintf W3CDTF waitpid wallclock wantarray warnock wcstombs wctomb webserver wellformedness whitelist whitespace wiki wildcard WindowsNT wordlist wordpad wordprocessor workflow wormhole wrapsuid writable writeable XKCD xor XS XSUB XSUBs yacc YAML YAPC yml yylex zsh