\documentclass[DIV=12,%
BCOR=0mm,%
headinclude=false,%
footinclude=false,open=any,%
fontsize=10pt,%
oneside,%
paper=210mm:11in]%
{scrbook}
\usepackage[noautomatic]{imakeidx}
\usepackage{microtype}
\usepackage{graphicx}
\usepackage{alltt}
\usepackage{verbatim}
\usepackage[shortlabels]{enumitem}
\usepackage{tabularx}
\usepackage[normalem]{ulem}
\def\hsout{\bgroup \ULdepth=-.55ex \ULset}
% https://tex.stackexchange.com/questions/22410/strikethrough-in-section-title
% Unclear if \protect \hsout is needed. Doesn't looks so
\DeclareRobustCommand{\sout}[1]{\texorpdfstring{\hsout{#1}}{#1}}
\usepackage{wrapfig}
% avoid breakage on multiple
and avoid the next [] to be eaten
\newcommand*{\forcelinebreak}{\strut\\*{}}
\newcommand*{\hairline}{%
\bigskip%
\noindent \hrulefill%
\bigskip%
}
% reverse indentation for biblio and play
\newenvironment*{amusebiblio}{
\leftskip=\parindent
\parindent=-\parindent
\smallskip
\indent
}{\smallskip}
\newenvironment*{amuseplay}{
\leftskip=\parindent
\parindent=-\parindent
\smallskip
\indent
}{\smallskip}
\newcommand*{\Slash}{\slash\hspace{0pt}}
% http://tex.stackexchange.com/questions/3033/forcing-linebreaks-in-url
\PassOptionsToPackage{hyphens}{url}\usepackage[hyperfootnotes=false,hidelinks,breaklinks=true]{hyperref}
\usepackage{bookmark}
\usepackage[english,shorthands=off]{babel}
\babelfont{rm}[Path=/home/wiki/.fonts/cm-unicode/,%
BoldFont=cmunbx.otf,%
BoldItalicFont=cmunbi.otf,%
ItalicFont=cmunti.otf]{cmunrm.otf}
\babelfont{tt}[Scale=MatchLowercase,%
Path=/home/wiki/.fonts/cm-unicode/,%
BoldFont=cmuntb.otf,%
BoldItalicFont=cmuntx.otf,%
ItalicFont=cmunit.otf]{cmuntt.otf}
\babelfont{sf}[Scale=MatchLowercase,%
Path=/home/wiki/.fonts/cm-unicode/,%
BoldFont=cmunsx.otf,%
BoldItalicFont=cmunso.otf,%
ItalicFont=cmunsi.otf]{cmunss.otf}
\renewcommand*{\partpagestyle}{empty}
% global style
\pagestyle{plain}
\usepackage{indentfirst}
% remove the numbering
\setcounter{secnumdepth}{-2}
% remove labels from the captions
\renewcommand*{\captionformat}{}
\renewcommand*{\figureformat}{}
\renewcommand*{\tableformat}{}
\KOMAoption{captions}{belowfigure,nooneline}
\addtokomafont{caption}{\centering}
\deffootnote[3em]{0em}{4em}{\textsuperscript{\thefootnotemark}~}
\addtokomafont{disposition}{\rmfamily}
\addtokomafont{descriptionlabel}{\rmfamily}
\frenchspacing
% avoid vertical glue
\raggedbottom
% this will generate overfull boxes, so we need to set a tolerance
% \pretolerance=1000
% pretolerance is what is accepted for a paragraph without
% hyphenation, so it makes sense to be strict here and let the user
% accept tweak the tolerance instead.
\tolerance=200
% Additional tolerance for bad paragraphs only
\setlength{\emergencystretch}{30pt}
% (try to) forbid widows/orphans
\clubpenalty=10000
\widowpenalty=10000
% given that we said footinclude=false, this should be safe
\setlength{\footskip}{2\baselineskip}
\setlength{\parindent}{15pt}
\title{Perl Tricks}
\date{}
\author{Stefan Hornburg (Racke)}
\subtitle{}
% https://groups.google.com/d/topic/comp.text.tex/6fYmcVMbSbQ/discussion
\hypersetup{%
pdfencoding=auto,
pdftitle={Perl Tricks},%
pdfauthor={Stefan Hornburg (Racke)},%
pdfsubject={},%
pdfkeywords={perl; CPAN; Moo; Tests; DateTime; MySQL; PostgreSQL; MariaDB; Charts; Dancer; Git; Travis}%
}
\begin{document}
\begin{titlepage}
\strut\vskip 2em
\begin{center}
{\usekomafont{title}{\huge Perl Tricks\par}}%
\vskip 1em
\vskip 2em
{\usekomafont{author}{Stefan Hornburg (Racke)\par}}%
\vskip 1.5em
\vfill
\strut\par
\end{center}
\end{titlepage}
\cleardoublepage
\tableofcontents
% start a new right-handed page
\cleardoublepage
\chapter{OO in Perl}
\section{namespace::clean}
It is a best practice to use
\texttt{
namespace::clean
}
in your class or your role
after
\texttt{
use ...
}
statements. Otherwise imported functions
double as methods for your class, which can have unexpected side effects which
are really hard to track down.
\chapter{Using Moo}
\section{Types for Moo}
We can recommend to use \href{https://metacpan.org/pod/Type::Tiny}{Type::Tiny} instead of \href{https://metacpan.org/pod/MooX::Types::MooseLike}{MooX::Types::Mooselike}. The latter is not Moose-friendly, while
Type::Tiny types get inflated to full Moose types if you happen to play with them in Moose. Also they are faster and we get better coercion in Moo for free.
One thing you may not have spotted for Type::Tiny which is useful\dots{}
it overloads \textbar{} and \& for use in isa - very tidy.
\begin{alltt}
use Moo;
use Types::Standard qw/ArrayRef HashRef InstanceOf/;
has fields => (
is => 'ro',
isa => ArrayRef [ InstanceOf ['Template::Flute::Form::Field'] ],
);
\end{alltt}
\subsection{ArrayRef}
\begin{alltt}
has config\_files => (
is => 'ro',
isa => ArrayRef,
default => sub \{ [] \},
);
\end{alltt}
\subsection{Maybe}
Sometimes it makes sense to allow \texttt{undef} as a value, e.g. if the builder isn't able to produce the promised type:
\begin{alltt}
has config => (
is => 'ro',
isa => Maybe[HashRef],
lazy => 1,
builder => '\_build\_config',
);
\end{alltt}
\section{Speed ups}
\begin{itemize}
\item\relax
\href{https://metacpan.org/pod/Class::XSAccessor}{Class::XSAccessor}
\item\relax
\href{https://metacpan.org/pod/Type::Tiny::XS}{Type::Tiny::XS}
\end{itemize}
\chapter{UTF-8}
Ensure that me use UTF-8 encoding for the standard input\Slash{}output streams:
\begin{alltt}
use open ':std', ':encoding(utf-8)';
\end{alltt}
\chapter{Using DateTime}
\section{Converting JSON dates}
APIs often using JSON as output. A JSON date looks like that:
\begin{alltt}
\end{alltt}
\section{Formatting}
\begin{alltt}
DateTime->now->strftime('\%Y-\%m-\%d');
\end{alltt}
\section{Week}
This function determines the first day of the week for a given year:
\begin{alltt}
sub first\_day\_of\_week
\{
my (\$year, \$week) = @\_;
\# Week 1 is defined as the one containing January 4:
DateTime
->new( year => \$year, month => 1, day => 4 )
->add( weeks => (\$week - 1) )
->truncate( to => 'week' );
\}
\end{alltt}
\chapter{Parsing}
\section{Text}
Split text into an array of lines:
\begin{alltt}
my @lines = split /\textbackslash{}r?\textbackslash{}n/, \$content;
my \%email\_headers;
for my \$line (@lines) \{
if (\$line =\textasciitilde{} /\^{}(From\textbar{}To):\textbackslash{}s(.*)/) \{
\$email\_headers\{lc(\$1)\} = \$2;
\}
\}
\end{alltt}
\section{List of arguments}
The simplest way to parse a list of arguments separated by whitespace is the
\emph{split} function:
\begin{alltt}
my \$arglist = 'foo bar baz';
my @args = split (/\textbackslash{}s+/, \$arglist));
\end{alltt}
This doesn't work with a list of files when it includes filenames with
whitespaces:
\begin{itemize}
\item\relax
'foo bar'
\item\relax
'baz'
\end{itemize}
You can use the \emph{shellwords} function from the \href{https://metacpan.org/pod/Text::ParseWords}{Text::ParseWords} module in this
case:
\begin{alltt}
use Text::ParseWords;
my \$arglist = '"foo bar" baz';
my @args = shellwords(\$arglist);
\end{alltt}
\chapter{Regular expresssions}
\section{Wrap all urls in a text into a HTML link}
\begin{alltt}
\$text =\textasciitilde{}s\#(https?://\textbackslash{}S+?)(\textbackslash{}.*[\textbackslash{}s\textbackslash{}<,])\#\$1\$2\#igs;
\end{alltt}
\chapter{Recipes}
\section{Print version of installed Perl modules}
There is a very useful module called \emph{V} for printing out version information about installed Perl modules:
\begin{alltt}
perl -MV=Dancer2
Dancer2
/home/racke/perl5/perlbrew/perls/perl-5.24.0/lib/site\_perl/5.24.1/Dancer2.pm: 0.205000
/home/racke/perl5/perlbrew/perls/perl-5.24.0/lib/site\_perl/5.24.0/Dancer2.pm: 0.204001
\end{alltt}
\chapter{Convert images with Image::Magick}
\section{Resize by percents}
\begin{alltt}
\$ convert mypic.jpg -resize 25\% mypicsmall.jpg
\end{alltt}
\section{Create transparent picture}
\begin{alltt}
\$ convert -size 1000x1000 xc:transparent any-square.png
\end{alltt}
\chapter{CPAN modules - the good and the bad}
\texttt{File::Slurp} is deprecated, use for example \texttt{Path::Tiny} instead.
\section{Charts}
\href{https://metacpan.org/pod/Chart::Clicker}{Chart::Clicker}
\chapter{Writing tests}
\section{Test for warnings}
Always use \href{https://metacpan.org/pod/Test::Warnings}{Test::Warnings} to capture unexpected warnings in your tests:
\begin{alltt}
use Test::Warnings;
\end{alltt}
\section{Test whether result is one of multiple values}
\begin{alltt}
use Test::Deep;
my \$status = \$mws->GetServiceStatus;
cmp\_deeply \$status, any(qw/GREEN GREEN\_I YELLOW RED/),
"Test response of GetServiceStatus API method";
\end{alltt}
\section{Skipping tests}
Often tests are using an optional module or external resources. In that case we just skip these tests if
we haven't all pieces in the right place.
For example, if an environment variable isn't set
properly:
\begin{alltt}
if (\$ENV\{SOLR\_URL\}) \{
\$solr\_url = \$ENV\{SOLR\_URL\};
\}
else \{
plan skip\_all => "Please set environment variable SOLR\_URL.";
\}
\end{alltt}
\section{Provide useful information with \texttt{diag}}
Even if you think your tests won't fail, they might.
In this case it is very helpful to provide additional
information to trace down the source of the problem:
\begin{alltt}
\# check output
my @matches = \$out =\textasciitilde{} /Blue ball/g;
ok (@matches == 2, 'Test replacement in both lists')
\textbar{}\textbar{} diag "Matches: ", scalar(@matches), "Output: \$out";
\end{alltt}
A good alternative is to use \texttt{is} instead of \texttt{ok}, which
automatically provides diagnostics:
\begin{alltt}
\# check output
my @matches = \$out =\textasciitilde{} /Blue ball/g;
is (scalar(@matches), 2, 'Test replacement in both lists');
\end{alltt}
Also other test functions like \texttt{isa\_ok} print further information.
\section{Test coverage}
\href{https://metacpan.org/pod/Devel::Cover}{Devel::Cover} makes test coverage easy in
your distribution:
\begin{alltt}
cpanm Devel::Cover
perl Makefile.PL
make
cover -test
\end{alltt}
You can find more information in the blog post from \href{http://blogs.perl.org/users/neilb/2014/08/check-your-test-coverage-with-develcover.html}{Neil Bower}.
\chapter{Installing CPAN modules}
\section{cpanm}
You can install Perl modules from Git repositories, e.g.
\begin{alltt}
cpanm git@github.com:interchange/Amazon-MWS.git@topic/amazon-pay-2020-01-28
\end{alltt}
The part after the @ is a branch, tag or hashsum.
\section{Debian prerequisites}
\hyperdef{amuse}{debianprequisites}{}%
\label{textamuse:debianprequisites}%
Here we show you which libraries you need to install for binary Perl
modules (Debian and Ubuntu).
\subsection{DBD::MySQL}
This works for MySQL and MariaDB:
\begin{alltt}
\$ apt install libmysqlclient-dev
\end{alltt}
\subsection{DBD::ODBC}
\begin{alltt}
\$ apt install unixodbc-dev
\end{alltt}
\subsection{DBD::Pg}
\begin{alltt}
\$ apt install libpq-dev
\end{alltt}
\subsection{ File::LibMagic}
\begin{alltt}
\$ apt install libmagic-dev
\end{alltt}
\subsection{Imager}
You need to install a number of development packages for the different
image types \emph{before} installing Imager, e.g. on Debian:
\begin{alltt}
\$ apt install libjpeg-dev libpng-dev libgif-dev libtiff-dev libfreetype6-dev
\end{alltt}
\subsection{Net::LibIDN2}
\begin{alltt}
\$ apt install libidn2-dev
\end{alltt}
\subsection{Net::SSLeay, Crypt::OpenSSL::Random, Crypt::OpenSSL::X509, \dots{}}
\begin{alltt}
\$ apt install libssl-dev
\end{alltt}
\subsection{IO::Socket::SSL}
\begin{alltt}
\$ apt install zlib1g-dev
\end{alltt}
\subsection{XML::Parser, XML::Twig, \dots{}}
\begin{alltt}
\$ apt install libexpat1-dev
\end{alltt}
\subsection{XML::LibXML}
\begin{alltt}
\$ apt install libxml2-dev
\end{alltt}
\section{Tips for other modules}
\subsection{Dancer2}
For more speed, install recommended modules as well:
\begin{alltt}
cpanm --installdeps --with-recommends Dancer2
\end{alltt}
These are XS modules replacing pure Perl modules, e.g. \emph{HTTP::XSHeaders} or \emph{Type::Tiny::XS}.
\chapter{Patching CPAN modules}
If you want to make a patch for a CPAN module which doesn't provide a Git repository, \href{https://metacpan.org/pod/Git::CPAN::Patch}{Git::CPAN::Patch} comes in very handy:
\begin{alltt}
\% git-cpan clone WebService::Xero
creating WebService-Xero
created tag 'v0.10' (7dbe0fdd5c54307ce6ea6d6943ddf529e1a7ab8c)
created tag 'v0.11' (082ce463c0dec679710d0eecfbbaf47262526bff)
\end{alltt}
Create a branch for your patch:
\begin{alltt}
\% git checkout -b topic/enable-put-method
\end{alltt}
After done with patching, you can submit the changes as follows:
\begin{enumerate}[1.]
\item\relax
add your changes and commit
\item\relax
push patch to CPAN
\end{enumerate}
For example:
\begin{alltt}
\% git add -u
\% git commit -m "Enable PUT method in Xero agent."
[topic/enable-put-method 76c60c1] Enable PUT method in Xero agent.
\%
\end{alltt}
\chapter{Writing CPAN modules}
\section{Resources}
Please add resources for \href{https://metacpan.org/}{meta::cpan} to your Makefile.PL, e.g.
\begin{alltt}
META\_MERGE => \{
resources => \{
repository => 'https://github.com/interchange/interchange6-schema.git',
bugtracker => 'https://github.com/interchange/interchange6-schema/issues',
IRC => 'irc://irc.freenode.net/\#interchange',
\},
\},
\end{alltt}
\section{Prerequisites and minimum versions}
\subsection{Test::Deep}
\begin{description}
\item[{0.114}]
if you use \texttt{noneof}
\end{description}
\subsection{Type::Tiny}
\begin{description}
\item[{0.008}]
if you use \texttt{InstanceOf}
\end{description}
\section{Travis}
Before you commit and push your \texttt{.travis.yml} file,
make sure that file is valid:
\begin{alltt}
travis lint .travis.yml
\end{alltt}
\subsection{ Perl versions}
The lastest Perl version supported by Travis is \texttt{5.30} as of September 2020.
\subsection{Coverage reports}
\begin{alltt}
language: perl
perl:
- "5.10"
- "5.12"
- "5.14"
- "5.16"
- "5.18"
- "5.20"
- "5.22"
- "5.24"
- "5.28"
- "dev" \# installs latest developer release of perl
- "blead" \# builds perl from git
matrix:
include:
- perl: 5.28
env: COVERAGE=1 \# enables coverage+coveralls reporting
allow\_failures:
- perl: blead \# ignore failures for blead perl
sudo: false \# faster builds as long as you don't need sudo access
before\_install:
- eval \$(curl https://travis-perl.github.io/init) --auto
\end{alltt}
Please see \href{https://github.com/travis-perl/helpers}{Travis helpers} for complete
reference.
\chapter{Scripts}
Add missing columns with default values to CSV file:
\begin{alltt}
\$ perl -i -pe 's/\$/;0;/' data.csv
\end{alltt}
This one-liner removes carriage returns in a file:
\begin{alltt}
\$ perl -i -pe 's/\textbackslash{}r//g' data.csv
\end{alltt}
Turn file with multiples lines into a comma separated list:
\begin{alltt}
\$ cat myfile.txt
FOO
BAR
BAZ
\end{alltt}
\begin{alltt}
\$ perl -pe 's/\textbackslash{}r?\textbackslash{}n/,/g' myfile.txt
FOO,BAR,BAZ
\end{alltt}
% begin final page
\clearpage
% new page for the colophon
\thispagestyle{empty}
\begin{center}
Linuxia Wiki
\strut
\end{center}
\strut
\vfill
\begin{center}
Stefan Hornburg (Racke)
Perl Tricks
\bigskip
\bigskip
\textbf{wiki.linuxia.de}
\end{center}
% end final page with colophon
% end closing pages
\end{document}
% No format ID passed.