1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/doc/lib/pgBackRestDoc/Latex/DocLatexSection.pm

487 lines
16 KiB
Perl
Raw Normal View History

####################################################################################################################################
# DOC LATEX SECTION MODULE
####################################################################################################################################
package pgBackRestDoc::Latex::DocLatexSection;
use parent 'pgBackRestDoc::Common::DocExecute';
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRestDoc::Common::DocConfig;
use pgBackRestDoc::Common::DocManifest;
use pgBackRestDoc::Common::Log;
use pgBackRestDoc::Common::String;
####################################################################################################################################
# CONSTRUCTOR
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oManifest,
$strRenderOutKey,
$bExe
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'oManifest'},
{name => 'strRenderOutKey'},
{name => 'bExe'}
);
# Create the class hash
my $self = $class->SUPER::new('latex', $oManifest, $strRenderOutKey, $bExe);
bless $self, $class;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self}
);
}
####################################################################################################################################
# process
#
# Generate the site html
####################################################################################################################################
sub process
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my $strOperation = logDebugParam(__PACKAGE__ . '->process');
# Working variables
my $oPage = $self->{oDoc};
my $strLatex;
# Initialize page
my $strTitle = $oPage->paramGet('title');
my $strSubTitle = $oPage->paramGet('subtitle', false);
# Render sections
foreach my $oSection ($oPage->nodeList('section'))
{
$strLatex .= (defined($strLatex) ? "\n" : '') . $self->sectionProcess($oSection, undef, 1);
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strHtml', value => $strLatex, trace => true}
);
}
####################################################################################################################################
# sectionProcess
####################################################################################################################################
sub sectionProcess
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oSection,
$strSection,
$iDepth
) =
logDebugParam
(
__PACKAGE__ . '->sectionRender', \@_,
{name => 'oSection'},
{name => 'strSection', required => false},
{name => 'iDepth'}
);
if ($oSection->paramGet('log'))
{
&log(INFO, (' ' x ($iDepth + 1)) . 'process section: ' . $oSection->paramGet('path'));
}
# Create section type
my $strSectionTitle = $self->processText($oSection->nodeGet('title')->textGet());
$strSection .= (defined($strSection) ? ', ' : '') . "'${strSectionTitle}' " . ('Sub' x ($iDepth - 1)) . "Section";
# Create section comment
my $strLatex =
"% ${strSection}\n% " . ('-' x 130) . "\n";
# Exclude from table of contents if requested
if ($iDepth <= 3 && $oSection->paramTest('toc', 'n'))
{
$strLatex .= '\\addtocontents{toc}{\\protect\\setcounter{tocdepth}{' . ($iDepth - 1) . "}}\n";
}
# Create section name
$strLatex .= '\\';
if ($iDepth <= 3)
{
$strLatex .= ($iDepth > 1 ? ('sub' x ($iDepth - 1)) : '') . "section";
}
elsif ($iDepth == 4)
{
$strLatex .= 'paragraph';
}
else
{
confess &log(ASSERT, "section depth of ${iDepth} exceeds maximum");
}
$strLatex .= "\{${strSectionTitle}\}\\label{" . $oSection->paramGet('path', false) . "}\n";
# Reset table of contents numbering if the section was excluded
if ($iDepth <= 3 && $oSection->paramTest('toc', 'n'))
{
$strLatex .= '\\addtocontents{toc}{\\protect\\setcounter{tocdepth}{' . $iDepth . "}}\n";
}
foreach my $oChild ($oSection->nodeList())
{
&log(DEBUG, (' ' x ($iDepth + 2)) . 'process child ' . $oChild->nameGet());
# Execute a command
if ($oChild->nameGet() eq 'execute-list')
{
my $bShow = $oChild->paramTest('show', 'n') ? false : true;
my $strHostName = $self->{oManifest}->variableReplace($oChild->paramGet('host'));
if ($bShow)
{
$strLatex .=
"\n\\begin\{lstlisting\}[title=\{\\textnormal{\\textbf\{${strHostName}}} --- " .
$self->processText($oChild->nodeGet('title')->textGet()) . "}]\n";
}
foreach my $oExecute ($oChild->nodeList('execute'))
{
my $bExeShow = !$oExecute->paramTest('show', 'n');
my ($strCommand, $strOutput) = $self->execute(
$oSection, $self->{oManifest}->variableReplace($oChild->paramGet('host')), $oExecute,
{iIndent => $iDepth + 3, bShow => $bShow && $bExeShow});
if ($bShow && $bExeShow)
{
$strLatex .= "${strCommand}\n";
if (defined($strOutput))
{
$strLatex .= "\nOutput:\n\n${strOutput}\n";
}
}
}
if ($bShow)
{
$strLatex .=
"\\end{lstlisting}\n";
}
}
# Add code block
elsif ($oChild->nameGet() eq 'code-block')
{
my $strTitle = $self->{oManifest}->variableReplace($oChild->paramGet("title", false), 'latex');
if (defined($strTitle) && $strTitle eq '')
{
undef($strTitle)
}
# Begin the code listing
if (!defined($strTitle))
{
$strLatex .=
"\\vspace{.75em}\n";
}
$strLatex .=
"\\begin\{lstlisting\}";
# Add the title if one is provided
if (defined($strTitle))
{
$strLatex .= "[title=\{${strTitle}:\}]";
}
# End the code listing
$strLatex .=
"\n" .
trim($oChild->valueGet()) . "\n" .
"\\end{lstlisting}\n";
}
# Add table
elsif ($oChild->nameGet() eq 'table')
{
my $oHeader;
my @oyColumn;
if ($oChild->nodeTest('table-header'))
{
$oHeader = $oChild->nodeGet('table-header');
@oyColumn = $oHeader->nodeList('table-column');
}
my $strWidth =
'{' . (defined($oHeader) && $oHeader->paramTest('width') ? ($oHeader->paramGet('width') / 100) .
'\textwidth' : '\textwidth') . '}';
# Build the table
$strLatex .= "\\vspace{1em}\\newline\n\\begin{table}\n\\begin{tabularx}${strWidth}{|";
# Build the table header
foreach my $oColumn (@oyColumn)
{
my $strAlignCode;
my $strAlign = $oColumn->paramGet("align", false);
# If fill is specified then use X or the custom designed alignments in the preamble to fill and justify the columns.
if ($oColumn->paramTest('fill') && $oColumn->paramGet('fill', false) eq 'y')
{
if (!defined($strAlign) || $strAlign eq 'left')
{
$strAlignCode = 'X';
}
elsif ($strAlign eq 'right')
{
$strAlignCode = 'R';
}
elsif ($strAlign eq 'center')
{
$strAlignCode = 'C';
}
else
{
confess &log(ERROR, "align '${strAlign}' not valid when fill=y");
}
}
else
{
if (!defined($strAlign) || $strAlign eq 'left')
{
$strAlignCode = 'l';
}
elsif ($strAlign eq 'center')
{
$strAlignCode = 'c';
}
elsif ($strAlign eq 'right')
{
$strAlignCode = 'r';
}
else
{
confess &log(ERROR, "align '${strAlign}' not valid");
}
}
# $strLatex .= 'p{' . $oColumn->paramGet("width") . '} | ';
$strLatex .= $strAlignCode . ' | ';
}
# If table-header not provided then default the column alignment and fill by using the number of columns in the 1st row
if (!defined($oHeader))
{
my @oyRow = $oChild->nodeGet('table-data')->nodeList('table-row');
foreach my $oRowCell ($oyRow[0]->nodeList('table-cell'))
{
$strLatex .= 'X|';
}
}
$strLatex .= "}\n";
my $strLine;
if (defined($oHeader))
{
$strLatex .= "\\hline";
$strLatex .= "\\rowcolor{ltgray}\n";
foreach my $oColumn (@oyColumn)
{
$strLine .= (defined($strLine) ? ' & ' : '') . '\textbf{' . $self->processText($oColumn->textGet()) . '}';
}
$strLatex .= "${strLine}\\\\";
}
# Build the rows
foreach my $oRow ($oChild->nodeGet('table-data')->nodeList('table-row'))
{
$strLatex .= "\\hline\n";
undef($strLine);
foreach my $oRowCell ($oRow->nodeList('table-cell'))
{
$strLine .= (defined($strLine) ? ' & ' : '') . $self->processText($oRowCell->textGet());
}
$strLatex .= "${strLine}\\\\";
}
$strLatex .= "\\hline\n\\end{tabularx}\n";
# If there is a title for the table, add it. Ignore the label since LaTex will automatically generate numbered labels.
# e.g. Table 1:
if ($oChild->nodeGet("title", false))
{
$strLatex .= "\\caption{" . $self->processText($oChild->nodeGet("title")->textGet()) . "}\n";
}
$strLatex .= "\\end{table}\n";
}
# Add descriptive text
elsif ($oChild->nameGet() eq 'p')
{
$strLatex .= "\n\\begin{sloppypar}" . $self->processText($oChild->textGet()) . "\\end{sloppypar}\n";
}
# Add option descriptive text
elsif ($oChild->nameGet() eq 'option-description')
{
my $strOption = $oChild->paramGet("key");
my $oDescription = ${$self->{oReference}->{oConfigHash}}{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_DESCRIPTION};
if (!defined($oDescription))
{
confess &log(ERROR, "unable to find ${strOption} option in sections - try adding option?");
}
$strLatex .= "\n\\begin{sloppypar}" . $self->processText($oDescription) . "\\end{sloppypar}\n";
}
# Add cmd descriptive text
elsif ($oChild->nameGet() eq 'cmd-description')
{
my $strCommand = $oChild->paramGet("key");
my $oDescription = ${$self->{oReference}->{oConfigHash}}{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_DESCRIPTION};
if (!defined($oDescription))
{
confess &log(ERROR, "unable to find ${strCommand} command in sections - try adding command?");
}
$strLatex .= "\n\\begin{sloppypar}" . $self->processText($oDescription) . "\\end{sloppypar}\n";
}
# Add a list
elsif ($oChild->nameGet() eq 'list')
{
$strLatex .= "\n\\begin{itemize}";
foreach my $oListItem ($oChild->nodeList())
{
$strLatex .= "\n \\item " . $self->processText($oListItem->textGet());
}
$strLatex .= "\n\\end{itemize}";
}
# Add/remove config options
elsif ($oChild->nameGet() eq 'backrest-config' || $oChild->nameGet() eq 'postgres-config')
{
$strLatex .= $self->configProcess($oSection, $oChild, $iDepth + 3);
}
# Add a subsection
elsif ($oChild->nameGet() eq 'section')
{
$strLatex .= "\n" . $self->sectionProcess($oChild, $strSection, $iDepth + 1);
}
# Add an admonition (e.g. NOTE, WARNING, etc)
elsif ($oChild->nameGet() eq 'admonition')
{
$strLatex .= "\n\\vspace{.5em}\\begin{leftbar}";
$strLatex .= "\n\\begin{sloppypar}\\textit{\\textbf{" . uc($oChild->paramGet('type')) . ": }";
$strLatex .= $self->processText($oChild->textGet()) . "}\\end{sloppypar}";
$strLatex .= "\n\\end{leftbar}\n";
}
# Check if the child can be processed by a parent
else
{
$self->sectionChildProcess($oSection, $oChild, $iDepth + 1);
}
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strSection', value => $strLatex, trace => true}
);
}
####################################################################################################################################
# configProcess
####################################################################################################################################
sub configProcess
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oSection,
$oConfig,
$iDepth
) =
logDebugParam
(
__PACKAGE__ . '->configProcess', \@_,
{name => 'oSection'},
{name => 'oConfig'},
{name => 'iDepth'}
);
# Working variables
my $strLatex = '';
my $strFile;
my $strConfig;
my $bShow = true;
# Generate the config
if ($oConfig->nameGet() eq 'backrest-config')
{
($strFile, $strConfig, $bShow) = $self->backrestConfig($oSection, $oConfig, $iDepth);
}
else
{
($strFile, $strConfig, $bShow) = $self->postgresConfig($oSection, $oConfig, $iDepth);
}
if ($bShow)
{
my $strHostName = $self->{oManifest}->variableReplace($oConfig->paramGet('host'));
# Replace _ in filename
$strFile = $self->variableReplace($strFile);
# Render the config
$strLatex =
"\n\\begin\{lstlisting\}[title=\{\\textnormal{\\textbf\{${strHostName}}}:\\textnormal{\\texttt\{${strFile}}} --- " .
$self->processText($oConfig->nodeGet('title')->textGet()) . "}]\n" .
(defined($strConfig) ? $strConfig : '') .
"\\end{lstlisting}\n";
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strConfig', value => $strLatex, trace => true}
);
}
1;