mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-14 03:58:18 +00:00
1419 lines
45 KiB
Perl
1419 lines
45 KiB
Perl
|
###############################################################################
|
||
|
#
|
||
|
# Package: NaturalDocs::Settings
|
||
|
#
|
||
|
###############################################################################
|
||
|
#
|
||
|
# A package to handle the command line and various other program settings.
|
||
|
#
|
||
|
###############################################################################
|
||
|
|
||
|
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
|
||
|
# Natural Docs is licensed under the GPL
|
||
|
|
||
|
use Cwd ();
|
||
|
|
||
|
use NaturalDocs::Settings::BuildTarget;
|
||
|
|
||
|
use strict;
|
||
|
use integer;
|
||
|
|
||
|
package NaturalDocs::Settings;
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Information
|
||
|
|
||
|
=pod begin nd
|
||
|
|
||
|
Topic: Usage and Dependencies
|
||
|
|
||
|
- The <Constant Functions> can be called immediately.
|
||
|
|
||
|
- Prior to initialization, <NaturalDocs::Builder> must have all its output packages registered.
|
||
|
|
||
|
- To initialize, call <Load()>. All functions except <InputDirectoryNameOf()> will then be available.
|
||
|
|
||
|
- <GenerateDirectoryNames()> must be called before <InputDirectoryNameOf()> will work. Currently it is called by
|
||
|
<NaturalDocs::Menu->LoadAndUpdate()>.
|
||
|
|
||
|
|
||
|
Architecture: Internal Overview
|
||
|
|
||
|
- <Load()> first parses the command line, gathering all the settings and checking for errors. All <NaturalDocs::Builder>
|
||
|
packages must be registered before this is called because it needs their command line options.
|
||
|
<NaturalDocs::Project->ReparseEverything()> and <NaturalDocs::Project->RebuildEverything()> are called right away if -r
|
||
|
or -ro are used.
|
||
|
|
||
|
- Output directories are *not* named at this point. See <Named Directories>.
|
||
|
|
||
|
- The previous settings from the last time Natural Docs was run are loaded and compared to the current settings.
|
||
|
<NaturalDocs::Project->ReparseEverything()> and <NaturalDocs::Project->RebuildEverything()> are called if there are
|
||
|
any differences that warrant it.
|
||
|
|
||
|
- It then waits for <GenerateDirectoryNames()> to be called by <NaturalDocs::Menu>. The reason for this is that the
|
||
|
previous directory names are stored as hints in the menu file, for reasons explained in <Named Directories>. Once that
|
||
|
happens all the unnamed directories have names generated for them so everything is named. The package is completely
|
||
|
set up.
|
||
|
|
||
|
- The input directories are stored in an array instead of a hash because the order they were declared in matters. If two
|
||
|
people use multiple input directories on separate computers without sharing a menu file, they should at least get consistent
|
||
|
directory names by declaring them in the same order.
|
||
|
|
||
|
|
||
|
Architecture: Named Directories
|
||
|
|
||
|
Ever since Natural Docs introduced multiple input directories in 1.16, they've had to be named. Since they don't necessarily
|
||
|
extend from the same root anymore, they can't share an output directory without the risk of file name conflicts. There was
|
||
|
an early attempt at giving them actual names, but now they're just numbered from 1.
|
||
|
|
||
|
Directory names aren't generated right away. It waits for <Menu.txt> to load because that holds the obfuscated names from
|
||
|
the last run. <NaturalDocs::Menu> then calls <GenerateDirectoryNames()> and passes those along as hints.
|
||
|
<GenerateDirectoryNames()> then applies them to any matches and generates new ones for any remaining. This is done so
|
||
|
that output page locations can remain consistent when built on multiple computers, so long as the menu file is shared. I tend
|
||
|
to think the menu file is the most likely configuration file to be shared.
|
||
|
|
||
|
|
||
|
Architecture: Removed Directories
|
||
|
|
||
|
Directories that were part of the previous run but aren't anymore are still stored in the package. The primary reason, though
|
||
|
there may be others, is file purging. If an input directory is removed, all the output files that were generated from anything
|
||
|
in it need to be removed. To find out what the output file name was for a removed source file, it needs to be able to split it
|
||
|
from it's original input directory and know what that directory was named. If this didn't happen those output files would be
|
||
|
orphaned, as was the case prior to 1.32.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Variables
|
||
|
|
||
|
|
||
|
# handle: PREVIOUS_SETTINGS_FILEHANDLE
|
||
|
# The file handle used with <PreviousSettings.nd>.
|
||
|
|
||
|
# array: inputDirectories
|
||
|
# An array of input directories.
|
||
|
my @inputDirectories;
|
||
|
|
||
|
# array: inputDirectoryNames
|
||
|
# An array of the input directory names. Each name corresponds to the directory of the same index in <inputDirectories>.
|
||
|
my @inputDirectoryNames;
|
||
|
|
||
|
# array: imageDirectories
|
||
|
# An array of image directories.
|
||
|
my @imageDirectories;
|
||
|
|
||
|
# array: imageDirectoryNames
|
||
|
# An array of the image directory names. Each name corresponds to the directory of the same index in <imageDirectories>.
|
||
|
my @imageDirectoryNames;
|
||
|
|
||
|
# array: relativeImageDirectories
|
||
|
# An array of the relative paths for images. The asterisks found in the command line are not present.
|
||
|
my @relativeImageDirectories;
|
||
|
|
||
|
# array: excludedInputDirectories
|
||
|
# An array of input directories to exclude.
|
||
|
my @excludedInputDirectories;
|
||
|
|
||
|
# array: removedInputDirectories
|
||
|
# An array of input directories that were once in the command line but are no longer.
|
||
|
my @removedInputDirectories;
|
||
|
|
||
|
# array: removedInputDirectoryNames
|
||
|
# An array of the removed input directories' names. Each name corresponds to the directory of the same index in
|
||
|
# <removedInputDirectories>.
|
||
|
my @removedInputDirectoryNames;
|
||
|
|
||
|
# array: removedImageDirectories
|
||
|
# An array of image directories that were once in the command line but are no longer.
|
||
|
my @removedImageDirectories;
|
||
|
|
||
|
# array: removedImageDirectoryNames
|
||
|
# An array of the removed image directories' names. Each name corresponds to the directory of the same index in
|
||
|
# <removedImageDirectories>.
|
||
|
my @removedImageDirectoryNames;
|
||
|
|
||
|
# var: projectDirectory
|
||
|
# The project directory.
|
||
|
my $projectDirectory;
|
||
|
|
||
|
# array: buildTargets
|
||
|
# An array of <NaturalDocs::Settings::BuildTarget>s.
|
||
|
my @buildTargets;
|
||
|
|
||
|
# var: documentedOnly
|
||
|
# Whether undocumented code aspects should be included in the output.
|
||
|
my $documentedOnly;
|
||
|
|
||
|
# int: tabLength
|
||
|
# The number of spaces in tabs.
|
||
|
my $tabLength;
|
||
|
|
||
|
# bool: noAutoGroup
|
||
|
# Whether auto-grouping is turned off.
|
||
|
my $noAutoGroup;
|
||
|
|
||
|
# bool: onlyFileTitles
|
||
|
# Whether source files should always use the file name as the title.
|
||
|
my $onlyFileTitles;
|
||
|
|
||
|
# bool: isQuiet
|
||
|
# Whether the script should be run in quiet mode or not.
|
||
|
my $isQuiet;
|
||
|
|
||
|
# bool: rebuildData
|
||
|
# WHether most data files should be ignored and rebuilt.
|
||
|
my $rebuildData;
|
||
|
|
||
|
# array: styles
|
||
|
# An array of style names to use, most important first.
|
||
|
my @styles;
|
||
|
|
||
|
# var: charset
|
||
|
# The character encoding of the source files, and thus the output.
|
||
|
my $charset;
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Files
|
||
|
|
||
|
|
||
|
#
|
||
|
# File: PreviousSettings.nd
|
||
|
#
|
||
|
# Stores the previous command line settings.
|
||
|
#
|
||
|
# Format:
|
||
|
#
|
||
|
# > [BINARY_FORMAT]
|
||
|
# > [VersionInt: app version]
|
||
|
#
|
||
|
# The file starts with the standard <BINARY_FORMAT> <VersionInt> header.
|
||
|
#
|
||
|
# > [UInt8: tab length]
|
||
|
# > [UInt8: documented only (0 or 1)]
|
||
|
# > [UInt8: no auto-group (0 or 1)]
|
||
|
# > [UInt8: only file titles (0 or 1)]
|
||
|
# > [AString16: charset]
|
||
|
# >
|
||
|
# > [UInt8: number of input directories]
|
||
|
# > [AString16: input directory] [AString16: input directory name] ...
|
||
|
#
|
||
|
# A count of input directories, then that number of directory/name pairs.
|
||
|
#
|
||
|
# > [UInt8: number of output targets]
|
||
|
# > [AString16: output directory] [AString16: output format command line option] ...
|
||
|
#
|
||
|
# A count of output targets, then that number of directory/format pairs.
|
||
|
#
|
||
|
#
|
||
|
# Revisions:
|
||
|
#
|
||
|
# 1.4:
|
||
|
#
|
||
|
# - Added only file titles.
|
||
|
#
|
||
|
# 1.33:
|
||
|
#
|
||
|
# - Added charset.
|
||
|
#
|
||
|
# 1.3:
|
||
|
#
|
||
|
# - Removed headers-only, which was a 0/1 UInt8 after tab length.
|
||
|
# - Change auto-group level (1 = no, 2 = yes, 3 = full only) to no auto-group (0 or 1).
|
||
|
#
|
||
|
# 1.22:
|
||
|
#
|
||
|
# - Added auto-group level.
|
||
|
#
|
||
|
# 1.2:
|
||
|
#
|
||
|
# - File was added to the project. Prior to 1.2, it didn't exist.
|
||
|
#
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Action Functions
|
||
|
|
||
|
#
|
||
|
# Function: Load
|
||
|
#
|
||
|
# Loads and parses all settings from the command line and configuration files. Will exit if the options are invalid or the syntax
|
||
|
# reference was requested.
|
||
|
#
|
||
|
sub Load
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
$self->ParseCommandLine();
|
||
|
$self->LoadAndComparePreviousSettings();
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: Save
|
||
|
#
|
||
|
# Saves all settings in configuration files to disk.
|
||
|
#
|
||
|
sub Save
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
$self->SavePreviousSettings();
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: GenerateDirectoryNames
|
||
|
#
|
||
|
# Generates names for each of the input and image directories, which can later be retrieved with <InputDirectoryNameOf()>
|
||
|
# and <ImageDirectoryNameOf()>.
|
||
|
#
|
||
|
# Parameters:
|
||
|
#
|
||
|
# inputHints - A hashref of suggested input directory names, where the keys are the directories and the values are the names.
|
||
|
# These take precedence over anything generated. You should include names for directories that are no longer in
|
||
|
# the command line. This parameter may be undef.
|
||
|
# imageHints - Same as inputHints, only for the image directories.
|
||
|
#
|
||
|
sub GenerateDirectoryNames #(hashref inputHints, hashref imageHints)
|
||
|
{
|
||
|
my ($self, $inputHints, $imageHints) = @_;
|
||
|
|
||
|
my %usedInputNames;
|
||
|
my %usedImageNames;
|
||
|
|
||
|
|
||
|
if (defined $inputHints)
|
||
|
{
|
||
|
# First, we have to convert all non-numeric names to numbers, since they may come from a pre-1.32 menu file. We do it
|
||
|
# here instead of in NaturalDocs::Menu to keep the naming scheme centralized.
|
||
|
|
||
|
my @names = values %$inputHints;
|
||
|
my $hasNonNumeric;
|
||
|
|
||
|
foreach my $name (@names)
|
||
|
{
|
||
|
if ($name !~ /^[0-9]+$/)
|
||
|
{
|
||
|
$hasNonNumeric = 1;
|
||
|
last;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
if ($hasNonNumeric)
|
||
|
{
|
||
|
# Hash mapping old names to new names.
|
||
|
my %conversion;
|
||
|
|
||
|
# The sequential number to use. Starts at two because we want 'default' to be one.
|
||
|
my $currentNumber = 2;
|
||
|
|
||
|
# If there's only one name, we set it to one no matter what it was set to before.
|
||
|
if (scalar @names == 1)
|
||
|
{ $conversion{$names[0]} = 1; }
|
||
|
else
|
||
|
{
|
||
|
# We sort the list first because we want the end result to be predictable. This conversion could be happening on many
|
||
|
# machines, and they may not all specify the input directories in the same order. They need to all come up with the
|
||
|
# same result.
|
||
|
@names = sort @names;
|
||
|
|
||
|
foreach my $name (@names)
|
||
|
{
|
||
|
if ($name eq 'default')
|
||
|
{ $conversion{$name} = 1; }
|
||
|
else
|
||
|
{
|
||
|
$conversion{$name} = $currentNumber;
|
||
|
$currentNumber++;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
# Convert them to the new names.
|
||
|
foreach my $directory (keys %$inputHints)
|
||
|
{
|
||
|
$inputHints->{$directory} = $conversion{ $inputHints->{$directory} };
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
# Now we apply all the names from the hints, and save any unused ones as removed directories.
|
||
|
|
||
|
for (my $i = 0; $i < scalar @inputDirectories; $i++)
|
||
|
{
|
||
|
if (exists $inputHints->{$inputDirectories[$i]})
|
||
|
{
|
||
|
$inputDirectoryNames[$i] = $inputHints->{$inputDirectories[$i]};
|
||
|
$usedInputNames{ $inputDirectoryNames[$i] } = 1;
|
||
|
delete $inputHints->{$inputDirectories[$i]};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
# Any remaining hints are saved as removed directories.
|
||
|
|
||
|
while (my ($directory, $name) = each %$inputHints)
|
||
|
{
|
||
|
push @removedInputDirectories, $directory;
|
||
|
push @removedInputDirectoryNames, $name;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
if (defined $imageHints)
|
||
|
{
|
||
|
# Image directory names were never non-numeric, so there is no conversion. Apply all the names from the hints.
|
||
|
|
||
|
for (my $i = 0; $i < scalar @imageDirectories; $i++)
|
||
|
{
|
||
|
if (exists $imageHints->{$imageDirectories[$i]})
|
||
|
{
|
||
|
$imageDirectoryNames[$i] = $imageHints->{$imageDirectories[$i]};
|
||
|
$usedImageNames{ $imageDirectoryNames[$i] } = 1;
|
||
|
delete $imageHints->{$imageDirectories[$i]};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
# Any remaining hints are saved as removed directories.
|
||
|
|
||
|
while (my ($directory, $name) = each %$imageHints)
|
||
|
{
|
||
|
push @removedImageDirectories, $directory;
|
||
|
push @removedImageDirectoryNames, $name;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
# Now we generate names for anything remaining.
|
||
|
|
||
|
my $inputCounter = 1;
|
||
|
|
||
|
for (my $i = 0; $i < scalar @inputDirectories; $i++)
|
||
|
{
|
||
|
if (!defined $inputDirectoryNames[$i])
|
||
|
{
|
||
|
while (exists $usedInputNames{$inputCounter})
|
||
|
{ $inputCounter++; };
|
||
|
|
||
|
$inputDirectoryNames[$i] = $inputCounter;
|
||
|
$usedInputNames{$inputCounter} = 1;
|
||
|
|
||
|
$inputCounter++;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
my $imageCounter = 1;
|
||
|
|
||
|
for (my $i = 0; $i < scalar @imageDirectories; $i++)
|
||
|
{
|
||
|
if (!defined $imageDirectoryNames[$i])
|
||
|
{
|
||
|
while (exists $usedImageNames{$imageCounter})
|
||
|
{ $imageCounter++; };
|
||
|
|
||
|
$imageDirectoryNames[$i] = $imageCounter;
|
||
|
$usedImageNames{$imageCounter} = 1;
|
||
|
|
||
|
$imageCounter++;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Information Functions
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: InputDirectories
|
||
|
#
|
||
|
# Returns an arrayref of input directories. Do not change.
|
||
|
#
|
||
|
# This will not return any removed input directories.
|
||
|
#
|
||
|
sub InputDirectories
|
||
|
{ return \@inputDirectories; };
|
||
|
|
||
|
#
|
||
|
# Function: InputDirectoryNameOf
|
||
|
#
|
||
|
# Returns the generated name of the passed input directory. <GenerateDirectoryNames()> must be called once before this
|
||
|
# function is available.
|
||
|
#
|
||
|
# If a name for a removed input directory is available, it will be returned as well.
|
||
|
#
|
||
|
sub InputDirectoryNameOf #(directory)
|
||
|
{
|
||
|
my ($self, $directory) = @_;
|
||
|
|
||
|
for (my $i = 0; $i < scalar @inputDirectories; $i++)
|
||
|
{
|
||
|
if ($directory eq $inputDirectories[$i])
|
||
|
{ return $inputDirectoryNames[$i]; };
|
||
|
};
|
||
|
|
||
|
for (my $i = 0; $i < scalar @removedInputDirectories; $i++)
|
||
|
{
|
||
|
if ($directory eq $removedInputDirectories[$i])
|
||
|
{ return $removedInputDirectoryNames[$i]; };
|
||
|
};
|
||
|
|
||
|
return undef;
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: SplitFromInputDirectory
|
||
|
#
|
||
|
# Takes an input file name and returns the array ( inputDirectory, relativePath ).
|
||
|
#
|
||
|
# If the file cannot be split from an input directory, it will try to do it with the removed input directories.
|
||
|
#
|
||
|
sub SplitFromInputDirectory #(file)
|
||
|
{
|
||
|
my ($self, $file) = @_;
|
||
|
|
||
|
foreach my $directory (@inputDirectories, @removedInputDirectories)
|
||
|
{
|
||
|
if (NaturalDocs::File->IsSubPathOf($directory, $file))
|
||
|
{ return ( $directory, NaturalDocs::File->MakeRelativePath($directory, $file) ); };
|
||
|
};
|
||
|
|
||
|
return ( );
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: ImageDirectories
|
||
|
#
|
||
|
# Returns an arrayref of image directories. Do not change.
|
||
|
#
|
||
|
# This will not return any removed image directories.
|
||
|
#
|
||
|
sub ImageDirectories
|
||
|
{ return \@imageDirectories; };
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: ImageDirectoryNameOf
|
||
|
#
|
||
|
# Returns the generated name of the passed image or input directory. <GenerateDirectoryNames()> must be called once before
|
||
|
# this function is available.
|
||
|
#
|
||
|
# If a name for a removed input or image directory is available, it will be returned as well.
|
||
|
#
|
||
|
sub ImageDirectoryNameOf #(directory)
|
||
|
{
|
||
|
my ($self, $directory) = @_;
|
||
|
|
||
|
for (my $i = 0; $i < scalar @imageDirectories; $i++)
|
||
|
{
|
||
|
if ($directory eq $imageDirectories[$i])
|
||
|
{ return $imageDirectoryNames[$i]; };
|
||
|
};
|
||
|
|
||
|
for (my $i = 0; $i < scalar @removedImageDirectories; $i++)
|
||
|
{
|
||
|
if ($directory eq $removedImageDirectories[$i])
|
||
|
{ return $removedImageDirectoryNames[$i]; };
|
||
|
};
|
||
|
|
||
|
return undef;
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: SplitFromImageDirectory
|
||
|
#
|
||
|
# Takes an input image file name and returns the array ( imageDirectory, relativePath ).
|
||
|
#
|
||
|
# If the file cannot be split from an image directory, it will try to do it with the removed image directories.
|
||
|
#
|
||
|
sub SplitFromImageDirectory #(file)
|
||
|
{
|
||
|
my ($self, $file) = @_;
|
||
|
|
||
|
foreach my $directory (@imageDirectories, @removedImageDirectories)
|
||
|
{
|
||
|
if (NaturalDocs::File->IsSubPathOf($directory, $file))
|
||
|
{ return ( $directory, NaturalDocs::File->MakeRelativePath($directory, $file) ); };
|
||
|
};
|
||
|
|
||
|
return ( );
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: RelativeImageDirectories
|
||
|
#
|
||
|
# Returns an arrayref of relative image directories. Do not change.
|
||
|
#
|
||
|
sub RelativeImageDirectories
|
||
|
{ return \@relativeImageDirectories; };
|
||
|
|
||
|
|
||
|
# Function: ExcludedInputDirectories
|
||
|
# Returns an arrayref of input directories to exclude. Do not change.
|
||
|
sub ExcludedInputDirectories
|
||
|
{ return \@excludedInputDirectories; };
|
||
|
|
||
|
|
||
|
# Function: BuildTargets
|
||
|
# Returns an arrayref of <NaturalDocs::Settings::BuildTarget>s. Do not change.
|
||
|
sub BuildTargets
|
||
|
{ return \@buildTargets; };
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: OutputDirectoryOf
|
||
|
#
|
||
|
# Returns the output directory of a builder object.
|
||
|
#
|
||
|
# Parameters:
|
||
|
#
|
||
|
# object - The builder object, whose class is derived from <NaturalDocs::Builder::Base>.
|
||
|
#
|
||
|
# Returns:
|
||
|
#
|
||
|
# The builder directory, or undef if the object wasn't found..
|
||
|
#
|
||
|
sub OutputDirectoryOf #(object)
|
||
|
{
|
||
|
my ($self, $object) = @_;
|
||
|
|
||
|
foreach my $buildTarget (@buildTargets)
|
||
|
{
|
||
|
if ($buildTarget->Builder() == $object)
|
||
|
{ return $buildTarget->Directory(); };
|
||
|
};
|
||
|
|
||
|
return undef;
|
||
|
};
|
||
|
|
||
|
|
||
|
# Function: Styles
|
||
|
# Returns an arrayref of the styles associated with the output.
|
||
|
sub Styles
|
||
|
{ return \@styles; };
|
||
|
|
||
|
# Function: ProjectDirectory
|
||
|
# Returns the project directory.
|
||
|
sub ProjectDirectory
|
||
|
{ return $projectDirectory; };
|
||
|
|
||
|
# Function: ProjectDataDirectory
|
||
|
# Returns the project data directory.
|
||
|
sub ProjectDataDirectory
|
||
|
{ return NaturalDocs::File->JoinPaths($projectDirectory, 'Data', 1); };
|
||
|
|
||
|
# Function: StyleDirectory
|
||
|
# Returns the main style directory.
|
||
|
sub StyleDirectory
|
||
|
{ return NaturalDocs::File->JoinPaths($FindBin::RealBin, 'Styles', 1); };
|
||
|
|
||
|
# Function: JavaScriptDirectory
|
||
|
# Returns the main JavaScript directory.
|
||
|
sub JavaScriptDirectory
|
||
|
{ return NaturalDocs::File->JoinPaths($FindBin::RealBin, 'JavaScript', 1); };
|
||
|
|
||
|
# Function: ConfigDirectory
|
||
|
# Returns the main configuration directory.
|
||
|
sub ConfigDirectory
|
||
|
{ return NaturalDocs::File->JoinPaths($FindBin::RealBin, 'Config', 1); };
|
||
|
|
||
|
# Function: DocumentedOnly
|
||
|
# Returns whether undocumented code aspects should be included in the output.
|
||
|
sub DocumentedOnly
|
||
|
{ return $documentedOnly; };
|
||
|
|
||
|
# Function: TabLength
|
||
|
# Returns the number of spaces tabs should be expanded to.
|
||
|
sub TabLength
|
||
|
{ return $tabLength; };
|
||
|
|
||
|
# Function: NoAutoGroup
|
||
|
# Returns whether auto-grouping is turned off.
|
||
|
sub NoAutoGroup
|
||
|
{ return $noAutoGroup; };
|
||
|
|
||
|
# Function: OnlyFileTitles
|
||
|
# Returns whether source files should always use the file name as the title.
|
||
|
sub OnlyFileTitles
|
||
|
{ return $onlyFileTitles; };
|
||
|
|
||
|
# Function: IsQuiet
|
||
|
# Returns whether the script should be run in quiet mode or not.
|
||
|
sub IsQuiet
|
||
|
{ return $isQuiet; };
|
||
|
|
||
|
# Function: RebuildData
|
||
|
# Returns whether all data files should be ignored and rebuilt.
|
||
|
sub RebuildData
|
||
|
{ return $rebuildData; };
|
||
|
|
||
|
# Function: CharSet
|
||
|
# Returns the character set, or undef if none.
|
||
|
sub CharSet
|
||
|
{ return $charset; };
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Constant Functions
|
||
|
|
||
|
#
|
||
|
# Function: AppVersion
|
||
|
#
|
||
|
# Returns Natural Docs' version number as an integer. Use <TextAppVersion()> to get a printable version.
|
||
|
#
|
||
|
sub AppVersion
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
return NaturalDocs::Version->FromString($self->TextAppVersion());
|
||
|
};
|
||
|
|
||
|
#
|
||
|
# Function: TextAppVersion
|
||
|
#
|
||
|
# Returns Natural Docs' version number as plain text.
|
||
|
#
|
||
|
sub TextAppVersion
|
||
|
{
|
||
|
return '1.4';
|
||
|
};
|
||
|
|
||
|
#
|
||
|
# Function: AppURL
|
||
|
#
|
||
|
# Returns a string of the project's current web address.
|
||
|
#
|
||
|
sub AppURL
|
||
|
{ return 'http://www.naturaldocs.org'; };
|
||
|
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Support Functions
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: ParseCommandLine
|
||
|
#
|
||
|
# Parses and validates the command line. Will cause the script to exit if the options ask for the syntax reference or
|
||
|
# are invalid.
|
||
|
#
|
||
|
sub ParseCommandLine
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
my %synonyms = ( 'input' => '-i',
|
||
|
'source' => '-i',
|
||
|
'excludeinput' => '-xi',
|
||
|
'excludesource' => '-xi',
|
||
|
'images' => '-img',
|
||
|
'output' => '-o',
|
||
|
'project' => '-p',
|
||
|
'documentedonly' => '-do',
|
||
|
'style' => '-s',
|
||
|
'rebuild' => '-r',
|
||
|
'rebuildoutput' => '-ro',
|
||
|
'tablength' => '-t',
|
||
|
'quiet' => '-q',
|
||
|
'headersonly' => '-ho',
|
||
|
'help' => '-h',
|
||
|
'autogroup' => '-ag',
|
||
|
'noautogroup' => '-nag',
|
||
|
'onlyfiletitles' => '-oft',
|
||
|
'onlyfiletitle' => '-oft',
|
||
|
'charset' => '-cs',
|
||
|
'characterset' => '-cs' );
|
||
|
|
||
|
|
||
|
my @errorMessages;
|
||
|
|
||
|
my $valueRef;
|
||
|
my $option;
|
||
|
|
||
|
my @outputStrings;
|
||
|
my @imageStrings;
|
||
|
|
||
|
|
||
|
# Sometimes $valueRef is set to $ignored instead of undef because we don't want certain errors to cause other,
|
||
|
# unnecessary errors. For example, if they set the input directory twice, we want to show that error and swallow the
|
||
|
# specified directory without complaint. Otherwise it would complain about the directory too as if it were random crap
|
||
|
# inserted into the command line.
|
||
|
my $ignored;
|
||
|
|
||
|
my $index = 0;
|
||
|
|
||
|
while ($index < scalar @ARGV)
|
||
|
{
|
||
|
my $arg = $ARGV[$index];
|
||
|
|
||
|
if (substr($arg, 0, 1) eq '-')
|
||
|
{
|
||
|
$option = lc($arg);
|
||
|
|
||
|
# Support options like -t2 as well as -t 2.
|
||
|
if ($option =~ /^([^0-9]+)([0-9]+)$/)
|
||
|
{
|
||
|
$option = $1;
|
||
|
splice(@ARGV, $index + 1, 0, $2);
|
||
|
};
|
||
|
|
||
|
# Convert long forms to short.
|
||
|
if (substr($option, 1, 1) eq '-')
|
||
|
{
|
||
|
# Strip all dashes.
|
||
|
my $newOption = $option;
|
||
|
$newOption =~ tr/-//d;
|
||
|
|
||
|
if (exists $synonyms{$newOption})
|
||
|
{ $option = $synonyms{$newOption}; }
|
||
|
}
|
||
|
|
||
|
if ($option eq '-i')
|
||
|
{
|
||
|
push @inputDirectories, undef;
|
||
|
$valueRef = \$inputDirectories[-1];
|
||
|
}
|
||
|
elsif ($option eq '-xi')
|
||
|
{
|
||
|
push @excludedInputDirectories, undef;
|
||
|
$valueRef = \$excludedInputDirectories[-1];
|
||
|
}
|
||
|
elsif ($option eq '-img')
|
||
|
{
|
||
|
push @imageStrings, undef;
|
||
|
$valueRef = \$imageStrings[-1];
|
||
|
}
|
||
|
elsif ($option eq '-p')
|
||
|
{
|
||
|
if (defined $projectDirectory)
|
||
|
{
|
||
|
push @errorMessages, 'You cannot have more than one project directory.';
|
||
|
$valueRef = \$ignored;
|
||
|
}
|
||
|
else
|
||
|
{ $valueRef = \$projectDirectory; };
|
||
|
}
|
||
|
elsif ($option eq '-o')
|
||
|
{
|
||
|
push @outputStrings, undef;
|
||
|
$valueRef = \$outputStrings[-1];
|
||
|
}
|
||
|
elsif ($option eq '-s')
|
||
|
{
|
||
|
$valueRef = \$styles[0];
|
||
|
}
|
||
|
elsif ($option eq '-t')
|
||
|
{
|
||
|
$valueRef = \$tabLength;
|
||
|
}
|
||
|
elsif ($option eq '-cs')
|
||
|
{
|
||
|
$valueRef = \$charset;
|
||
|
}
|
||
|
elsif ($option eq '-ag')
|
||
|
{
|
||
|
push @errorMessages, 'The -ag setting is no longer supported. You can use -nag (--no-auto-group) to turn off '
|
||
|
. "auto-grouping, but there aren't multiple levels anymore.";
|
||
|
$valueRef = \$ignored;
|
||
|
}
|
||
|
|
||
|
# Options that aren't followed by content.
|
||
|
else
|
||
|
{
|
||
|
$valueRef = undef;
|
||
|
|
||
|
if ($option eq '-r')
|
||
|
{
|
||
|
NaturalDocs::Project->ReparseEverything();
|
||
|
NaturalDocs::Project->RebuildEverything();
|
||
|
$rebuildData = 1;
|
||
|
}
|
||
|
elsif ($option eq '-ro')
|
||
|
{
|
||
|
NaturalDocs::Project->RebuildEverything();
|
||
|
}
|
||
|
elsif ($option eq '-do')
|
||
|
{ $documentedOnly = 1; }
|
||
|
elsif ($option eq '-oft')
|
||
|
{ $onlyFileTitles = 1; }
|
||
|
elsif ($option eq '-q')
|
||
|
{ $isQuiet = 1; }
|
||
|
elsif ($option eq '-ho')
|
||
|
{
|
||
|
push @errorMessages, 'The -ho setting is no longer supported. You can have Natural Docs skip over the source file '
|
||
|
. 'extensions by editing Languages.txt in your project directory.';
|
||
|
}
|
||
|
elsif ($option eq '-nag')
|
||
|
{ $noAutoGroup = 1; }
|
||
|
elsif ($option eq '-?' || $option eq '-h')
|
||
|
{
|
||
|
$self->PrintSyntax();
|
||
|
exit;
|
||
|
}
|
||
|
else
|
||
|
{ push @errorMessages, 'Unrecognized option ' . $option; };
|
||
|
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
# Is a segment of text, not an option...
|
||
|
else
|
||
|
{
|
||
|
if (defined $valueRef)
|
||
|
{
|
||
|
# We want to preserve spaces in paths.
|
||
|
if (defined $$valueRef)
|
||
|
{ $$valueRef .= ' '; };
|
||
|
|
||
|
$$valueRef .= $arg;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
push @errorMessages, 'Unrecognized element ' . $arg;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
$index++;
|
||
|
};
|
||
|
|
||
|
|
||
|
# Validate the style, if specified.
|
||
|
|
||
|
if ($styles[0])
|
||
|
{
|
||
|
my @stylePieces = split(/ +/, $styles[0]);
|
||
|
@styles = ( );
|
||
|
|
||
|
while (scalar @stylePieces)
|
||
|
{
|
||
|
if (lc($stylePieces[0]) eq 'custom')
|
||
|
{
|
||
|
push @errorMessages, 'The "Custom" style setting is no longer supported. Copy your custom style sheet to your '
|
||
|
. 'project directory and you can refer to it with -s.';
|
||
|
shift @stylePieces;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
# People may use styles with spaces in them. If a style doesn't exist, we need to join the pieces until we find one that
|
||
|
# does or we run out of pieces.
|
||
|
|
||
|
my $extras = 0;
|
||
|
my $success;
|
||
|
|
||
|
while ($extras < scalar @stylePieces)
|
||
|
{
|
||
|
my $style;
|
||
|
|
||
|
if (!$extras)
|
||
|
{ $style = $stylePieces[0]; }
|
||
|
else
|
||
|
{ $style = join(' ', @stylePieces[0..$extras]); };
|
||
|
|
||
|
my $cssFile = NaturalDocs::File->JoinPaths( $self->StyleDirectory(), $style . '.css' );
|
||
|
if (-e $cssFile)
|
||
|
{
|
||
|
push @styles, $style;
|
||
|
splice(@stylePieces, 0, 1 + $extras);
|
||
|
$success = 1;
|
||
|
last;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$cssFile = NaturalDocs::File->JoinPaths( $self->ProjectDirectory(), $style . '.css' );
|
||
|
|
||
|
if (-e $cssFile)
|
||
|
{
|
||
|
push @styles, $style;
|
||
|
splice(@stylePieces, 0, 1 + $extras);
|
||
|
$success = 1;
|
||
|
last;
|
||
|
}
|
||
|
else
|
||
|
{ $extras++; };
|
||
|
};
|
||
|
};
|
||
|
|
||
|
if (!$success)
|
||
|
{
|
||
|
push @errorMessages, 'The style "' . $stylePieces[0] . '" does not exist.';
|
||
|
shift @stylePieces;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
}
|
||
|
else
|
||
|
{ @styles = ( 'Default' ); };
|
||
|
|
||
|
|
||
|
# Decode and validate the output strings.
|
||
|
|
||
|
my %outputDirectories;
|
||
|
|
||
|
foreach my $outputString (@outputStrings)
|
||
|
{
|
||
|
my ($format, $directory) = split(/ /, $outputString, 2);
|
||
|
|
||
|
if (!defined $directory)
|
||
|
{ push @errorMessages, 'The -o option needs two parameters: -o [format] [directory]'; }
|
||
|
else
|
||
|
{
|
||
|
if (!NaturalDocs::File->PathIsAbsolute($directory))
|
||
|
{ $directory = NaturalDocs::File->JoinPaths(Cwd::cwd(), $directory, 1); };
|
||
|
|
||
|
$directory = NaturalDocs::File->CanonizePath($directory);
|
||
|
|
||
|
if (! -e $directory || ! -d $directory)
|
||
|
{
|
||
|
# They may have forgotten the format portion and the directory name had a space in it.
|
||
|
if (-e ($format . ' ' . $directory) && -d ($format . ' ' . $directory))
|
||
|
{
|
||
|
push @errorMessages, 'The -o option needs two parameters: -o [format] [directory]';
|
||
|
$format = undef;
|
||
|
}
|
||
|
else
|
||
|
{ push @errorMessages, 'The output directory ' . $directory . ' does not exist.'; }
|
||
|
}
|
||
|
elsif (exists $outputDirectories{$directory})
|
||
|
{ push @errorMessages, 'You cannot specify the output directory ' . $directory . ' more than once.'; }
|
||
|
else
|
||
|
{ $outputDirectories{$directory} = 1; };
|
||
|
|
||
|
if (defined $format)
|
||
|
{
|
||
|
my $builderPackage = NaturalDocs::Builder->OutputPackageOf($format);
|
||
|
|
||
|
if (defined $builderPackage)
|
||
|
{
|
||
|
push @buildTargets,
|
||
|
NaturalDocs::Settings::BuildTarget->New($builderPackage->New(), $directory);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
push @errorMessages, 'The output format ' . $format . ' doesn\'t exist or is not installed.';
|
||
|
$valueRef = \$ignored;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
if (!scalar @buildTargets)
|
||
|
{ push @errorMessages, 'You did not specify an output directory.'; };
|
||
|
|
||
|
|
||
|
# Decode and validate the image strings.
|
||
|
|
||
|
foreach my $imageString (@imageStrings)
|
||
|
{
|
||
|
if ($imageString =~ /^ *\*/)
|
||
|
{
|
||
|
# The below NaturalDocs::File functions assume everything is canonized.
|
||
|
$imageString = NaturalDocs::File->CanonizePath($imageString);
|
||
|
|
||
|
my ($volume, $directoryString) = NaturalDocs::File->SplitPath($imageString, 1);
|
||
|
my @directories = NaturalDocs::File->SplitDirectories($directoryString);
|
||
|
|
||
|
shift @directories;
|
||
|
|
||
|
$directoryString = NaturalDocs::File->JoinDirectories(@directories);
|
||
|
push @relativeImageDirectories, NaturalDocs::File->JoinPath($volume, $directoryString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!NaturalDocs::File->PathIsAbsolute($imageString))
|
||
|
{ $imageString = NaturalDocs::File->JoinPaths(Cwd::cwd(), $imageString, 1); };
|
||
|
|
||
|
$imageString = NaturalDocs::File->CanonizePath($imageString);
|
||
|
|
||
|
if (! -e $imageString || ! -d $imageString)
|
||
|
{ push @errorMessages, 'The image directory ' . $imageString . ' does not exist.'; };
|
||
|
|
||
|
push @imageDirectories, $imageString;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
# Make sure the input and project directories are specified, canonized, and exist.
|
||
|
|
||
|
if (scalar @inputDirectories)
|
||
|
{
|
||
|
for (my $i = 0; $i < scalar @inputDirectories; $i++)
|
||
|
{
|
||
|
if (!NaturalDocs::File->PathIsAbsolute($inputDirectories[$i]))
|
||
|
{ $inputDirectories[$i] = NaturalDocs::File->JoinPaths(Cwd::cwd(), $inputDirectories[$i], 1); };
|
||
|
|
||
|
$inputDirectories[$i] = NaturalDocs::File->CanonizePath($inputDirectories[$i]);
|
||
|
|
||
|
if (! -e $inputDirectories[$i] || ! -d $inputDirectories[$i])
|
||
|
{ push @errorMessages, 'The input directory ' . $inputDirectories[$i] . ' does not exist.'; };
|
||
|
};
|
||
|
}
|
||
|
else
|
||
|
{ push @errorMessages, 'You did not specify an input (source) directory.'; };
|
||
|
|
||
|
if (defined $projectDirectory)
|
||
|
{
|
||
|
if (!NaturalDocs::File->PathIsAbsolute($projectDirectory))
|
||
|
{ $projectDirectory = NaturalDocs::File->JoinPaths(Cwd::cwd(), $projectDirectory, 1); };
|
||
|
|
||
|
$projectDirectory = NaturalDocs::File->CanonizePath($projectDirectory);
|
||
|
|
||
|
if (! -e $projectDirectory || ! -d $projectDirectory)
|
||
|
{ push @errorMessages, 'The project directory ' . $projectDirectory . ' does not exist.'; };
|
||
|
|
||
|
# Create the Data subdirectory if it doesn't exist.
|
||
|
NaturalDocs::File->CreatePath( NaturalDocs::File->JoinPaths($projectDirectory, 'Data', 1) );
|
||
|
}
|
||
|
else
|
||
|
{ push @errorMessages, 'You did not specify a project directory.'; };
|
||
|
|
||
|
|
||
|
# Make sure the excluded input directories are canonized, and add the project and output directories to the list.
|
||
|
|
||
|
for (my $i = 0; $i < scalar @excludedInputDirectories; $i++)
|
||
|
{
|
||
|
if (!NaturalDocs::File->PathIsAbsolute($excludedInputDirectories[$i]))
|
||
|
{ $excludedInputDirectories[$i] = NaturalDocs::File->JoinPaths(Cwd::cwd(), $excludedInputDirectories[$i], 1); };
|
||
|
|
||
|
$excludedInputDirectories[$i] = NaturalDocs::File->CanonizePath($excludedInputDirectories[$i]);
|
||
|
};
|
||
|
|
||
|
push @excludedInputDirectories, $projectDirectory;
|
||
|
|
||
|
foreach my $buildTarget (@buildTargets)
|
||
|
{
|
||
|
push @excludedInputDirectories, $buildTarget->Directory();
|
||
|
};
|
||
|
|
||
|
|
||
|
# Determine the tab length, and default to four if not specified.
|
||
|
|
||
|
if (defined $tabLength)
|
||
|
{
|
||
|
if ($tabLength !~ /^[0-9]+$/)
|
||
|
{ push @errorMessages, 'The tab length must be a number.'; };
|
||
|
}
|
||
|
else
|
||
|
{ $tabLength = 4; };
|
||
|
|
||
|
|
||
|
# Strip any quotes off of the charset.
|
||
|
$charset =~ tr/\"//d;
|
||
|
|
||
|
|
||
|
# Exit with the error message if there was one.
|
||
|
|
||
|
if (scalar @errorMessages)
|
||
|
{
|
||
|
print join("\n", @errorMessages) . "\nType NaturalDocs -h to see the syntax reference.\n";
|
||
|
exit;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
#
|
||
|
# Function: PrintSyntax
|
||
|
#
|
||
|
# Prints the syntax reference.
|
||
|
#
|
||
|
sub PrintSyntax
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
# Make sure all line lengths are under 80 characters.
|
||
|
|
||
|
print
|
||
|
|
||
|
"Natural Docs, version " . $self->TextAppVersion() . "\n"
|
||
|
. $self->AppURL() . "\n"
|
||
|
. "This program is licensed under the GPL\n"
|
||
|
. "--------------------------------------\n"
|
||
|
. "\n"
|
||
|
. "Syntax:\n"
|
||
|
. "\n"
|
||
|
. " NaturalDocs -i [input (source) directory]\n"
|
||
|
. " (-i [input (source) directory] ...)\n"
|
||
|
. " -o [output format] [output directory]\n"
|
||
|
. " (-o [output format] [output directory] ...)\n"
|
||
|
. " -p [project directory]\n"
|
||
|
. " [options]\n"
|
||
|
. "\n"
|
||
|
. "Examples:\n"
|
||
|
. "\n"
|
||
|
. " NaturalDocs -i C:\\My Project\\Source -o HTML C:\\My Project\\Docs\n"
|
||
|
. " -p C:\\My Project\\Natural Docs\n"
|
||
|
. " NaturalDocs -i /src/project -o HTML /doc/project\n"
|
||
|
. " -p /etc/naturaldocs/project -s Small -q\n"
|
||
|
. "\n"
|
||
|
. "Required Parameters:\n"
|
||
|
. "\n"
|
||
|
. " -i [dir]\n--input [dir]\n--source [dir]\n"
|
||
|
. " Specifies an input (source) directory. Required.\n"
|
||
|
. " Can be specified multiple times.\n"
|
||
|
. "\n"
|
||
|
. " -o [fmt] [dir]\n--output [fmt] [dir]\n"
|
||
|
. " Specifies an output format and directory. Required.\n"
|
||
|
. " Can be specified multiple times, but only once per directory.\n"
|
||
|
. " Possible output formats:\n";
|
||
|
|
||
|
$self->PrintOutputFormats(' - ');
|
||
|
|
||
|
print
|
||
|
"\n"
|
||
|
. " -p [dir]\n--project [dir]\n"
|
||
|
. " Specifies the project directory. Required.\n"
|
||
|
. " There needs to be a unique project directory for every source directory.\n"
|
||
|
. "\n"
|
||
|
. "Optional Parameters:\n"
|
||
|
. "\n"
|
||
|
. " -s [style] ([style] [style] ...)\n--style [style] ([style] [style] ...)\n"
|
||
|
. " Specifies the CSS style when building HTML output. If multiple styles are\n"
|
||
|
. " specified, they will all be included in the order given.\n"
|
||
|
. "\n"
|
||
|
. " -img [image directory]\n--image [image directory]"
|
||
|
. " Specifies an image directory. Can be specified multiple times.\n"
|
||
|
. " Start with * to specify a relative directory, as in -img */images.\n"
|
||
|
. "\n"
|
||
|
. " -do\n--documented-only\n"
|
||
|
. " Specifies only documented code aspects should be included in the output.\n"
|
||
|
. "\n"
|
||
|
. " -t [len]\n--tab-length [len]\n"
|
||
|
. " Specifies the number of spaces tabs should be expanded to. This only needs\n"
|
||
|
. " to be set if you use tabs in example code and text diagrams. Defaults to 4.\n"
|
||
|
. "\n"
|
||
|
. " -xi [dir]\n--exclude-input [dir]\n--exclude-source [dir]\n"
|
||
|
. " Excludes an input (source) directory from the documentation.\n"
|
||
|
. " Automatically done for the project and output directories. Can\n"
|
||
|
. " be specified multiple times.\n"
|
||
|
. "\n"
|
||
|
. " -nag\n--no-auto-group\n"
|
||
|
. " Turns off auto-grouping completely.\n"
|
||
|
. "\n"
|
||
|
. " -oft\n--only-file-titles\n"
|
||
|
. " Source files will only use the file name as the title.\n"
|
||
|
. "\n"
|
||
|
. " -r\n--rebuild\n"
|
||
|
. " Rebuilds all output and data files from scratch.\n"
|
||
|
. " Does not affect the menu file.\n"
|
||
|
. "\n"
|
||
|
. " -ro\n--rebuild-output\n"
|
||
|
. " Rebuilds all output files from scratch.\n"
|
||
|
. "\n"
|
||
|
. " -q\n--quiet\n"
|
||
|
. " Suppresses all non-error output.\n"
|
||
|
. "\n"
|
||
|
. " -?\n -h\n--help\n"
|
||
|
. " Displays this syntax reference.\n";
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: PrintOutputFormats
|
||
|
#
|
||
|
# Prints all the possible output formats that can be specified with -o. Each one will be placed on its own line.
|
||
|
#
|
||
|
# Parameters:
|
||
|
#
|
||
|
# prefix - Characters to prefix each one with, such as for indentation.
|
||
|
#
|
||
|
sub PrintOutputFormats #(prefix)
|
||
|
{
|
||
|
my ($self, $prefix) = @_;
|
||
|
|
||
|
my $outputPackages = NaturalDocs::Builder::OutputPackages();
|
||
|
|
||
|
foreach my $outputPackage (@$outputPackages)
|
||
|
{
|
||
|
print $prefix . $outputPackage->CommandLineOption() . "\n";
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: LoadAndComparePreviousSettings
|
||
|
#
|
||
|
# Loads <PreviousSettings.nd> and compares the values there with those in the command line. If differences require it,
|
||
|
# sets <rebuildData> and/or <rebuildOutput>.
|
||
|
#
|
||
|
sub LoadAndComparePreviousSettings
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
my $fileIsOkay;
|
||
|
|
||
|
if (!NaturalDocs::Settings->RebuildData())
|
||
|
{
|
||
|
my $version;
|
||
|
|
||
|
if (NaturalDocs::BinaryFile->OpenForReading( NaturalDocs::Project->DataFile('PreviousSettings.nd'),
|
||
|
NaturalDocs::Version->FromString('1.4') ))
|
||
|
{ $fileIsOkay = 1; };
|
||
|
};
|
||
|
|
||
|
if (!$fileIsOkay)
|
||
|
{
|
||
|
# We need to reparse everything because --documented-only may have changed.
|
||
|
# We need to rebuild everything because --tab-length may have changed.
|
||
|
NaturalDocs::Project->ReparseEverything();
|
||
|
NaturalDocs::Project->RebuildEverything();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
my $raw;
|
||
|
|
||
|
# [UInt8: tab expansion]
|
||
|
# [UInt8: documented only (0 or 1)]
|
||
|
# [UInt8: no auto-group (0 or 1)]
|
||
|
# [UInt8: only file titles (0 or 1)]
|
||
|
# [AString16: charset]
|
||
|
|
||
|
my $prevTabLength = NaturalDocs::BinaryFile->GetUInt8();
|
||
|
my $prevDocumentedOnly = NaturalDocs::BinaryFile->GetUInt8();
|
||
|
my $prevNoAutoGroup = NaturalDocs::BinaryFile->GetUInt8();
|
||
|
my $prevOnlyFileTitles = NaturalDocs::BinaryFile->GetUInt8();
|
||
|
my $prevCharset = NaturalDocs::BinaryFile->GetAString16();
|
||
|
|
||
|
if ($prevTabLength != $self->TabLength())
|
||
|
{
|
||
|
# We need to rebuild all output because this affects all text diagrams.
|
||
|
NaturalDocs::Project->RebuildEverything();
|
||
|
};
|
||
|
|
||
|
if ($prevDocumentedOnly == 0)
|
||
|
{ $prevDocumentedOnly = undef; };
|
||
|
if ($prevNoAutoGroup == 0)
|
||
|
{ $prevNoAutoGroup = undef; };
|
||
|
if ($prevOnlyFileTitles == 0)
|
||
|
{ $prevOnlyFileTitles = undef; };
|
||
|
|
||
|
if ($prevDocumentedOnly != $self->DocumentedOnly() ||
|
||
|
$prevNoAutoGroup != $self->NoAutoGroup() ||
|
||
|
$prevOnlyFileTitles != $self->OnlyFileTitles())
|
||
|
{
|
||
|
NaturalDocs::Project->ReparseEverything();
|
||
|
};
|
||
|
|
||
|
if ($prevCharset ne $charset)
|
||
|
{ NaturalDocs::Project->RebuildEverything(); };
|
||
|
|
||
|
|
||
|
# [UInt8: number of input directories]
|
||
|
|
||
|
my $inputDirectoryCount = NaturalDocs::BinaryFile->GetUInt8();
|
||
|
|
||
|
while ($inputDirectoryCount)
|
||
|
{
|
||
|
# [AString16: input directory] [AString16: input directory name] ...
|
||
|
|
||
|
my $inputDirectory = NaturalDocs::BinaryFile->GetAString16();
|
||
|
my $inputDirectoryName = NaturalDocs::BinaryFile->GetAString16();
|
||
|
|
||
|
# Not doing anything with this for now.
|
||
|
|
||
|
$inputDirectoryCount--;
|
||
|
};
|
||
|
|
||
|
|
||
|
# [UInt8: number of output targets]
|
||
|
|
||
|
my $outputTargetCount = NaturalDocs::BinaryFile->GetUInt8();
|
||
|
|
||
|
# Keys are the directories, values are the command line options.
|
||
|
my %previousOutputDirectories;
|
||
|
|
||
|
while ($outputTargetCount)
|
||
|
{
|
||
|
# [AString16: output directory] [AString16: output format command line option] ...
|
||
|
|
||
|
my $outputDirectory = NaturalDocs::BinaryFile->GetAString16();
|
||
|
my $outputCommand = NaturalDocs::BinaryFile->GetAString16();
|
||
|
|
||
|
$previousOutputDirectories{$outputDirectory} = $outputCommand;
|
||
|
|
||
|
$outputTargetCount--;
|
||
|
};
|
||
|
|
||
|
# Check if any targets were added to the command line, or if their formats changed. We don't care if targets were
|
||
|
# removed.
|
||
|
my $buildTargets = $self->BuildTargets();
|
||
|
|
||
|
foreach my $buildTarget (@$buildTargets)
|
||
|
{
|
||
|
if (!exists $previousOutputDirectories{$buildTarget->Directory()} ||
|
||
|
$buildTarget->Builder()->CommandLineOption() ne $previousOutputDirectories{$buildTarget->Directory()})
|
||
|
{
|
||
|
NaturalDocs::Project->RebuildEverything();
|
||
|
last;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
NaturalDocs::BinaryFile->Close();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: SavePreviousSettings
|
||
|
#
|
||
|
# Saves the settings into <PreviousSettings.nd>.
|
||
|
#
|
||
|
sub SavePreviousSettings
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
NaturalDocs::BinaryFile->OpenForWriting( NaturalDocs::Project->DataFile('PreviousSettings.nd') );
|
||
|
|
||
|
# [UInt8: tab length]
|
||
|
# [UInt8: documented only (0 or 1)]
|
||
|
# [UInt8: no auto-group (0 or 1)]
|
||
|
# [UInt8: only file titles (0 or 1)]
|
||
|
# [AString16: charset]
|
||
|
# [UInt8: number of input directories]
|
||
|
|
||
|
my $inputDirectories = $self->InputDirectories();
|
||
|
|
||
|
NaturalDocs::BinaryFile->WriteUInt8($self->TabLength());
|
||
|
NaturalDocs::BinaryFile->WriteUInt8($self->DocumentedOnly() ? 1 : 0);
|
||
|
NaturalDocs::BinaryFile->WriteUInt8($self->NoAutoGroup() ? 1 : 0);
|
||
|
NaturalDocs::BinaryFile->WriteUInt8($self->OnlyFileTitles() ? 1 : 0);
|
||
|
NaturalDocs::BinaryFile->WriteAString16($charset);
|
||
|
NaturalDocs::BinaryFile->WriteUInt8(scalar @$inputDirectories);
|
||
|
|
||
|
foreach my $inputDirectory (@$inputDirectories)
|
||
|
{
|
||
|
my $inputDirectoryName = $self->InputDirectoryNameOf($inputDirectory);
|
||
|
|
||
|
# [AString16: input directory] [AString16: input directory name] ...
|
||
|
NaturalDocs::BinaryFile->WriteAString16($inputDirectory);
|
||
|
NaturalDocs::BinaryFile->WriteAString16($inputDirectoryName);
|
||
|
};
|
||
|
|
||
|
# [UInt8: number of output targets]
|
||
|
|
||
|
my $buildTargets = $self->BuildTargets();
|
||
|
NaturalDocs::BinaryFile->WriteUInt8(scalar @$buildTargets);
|
||
|
|
||
|
foreach my $buildTarget (@$buildTargets)
|
||
|
{
|
||
|
# [AString16: output directory] [AString16: output format command line option] ...
|
||
|
NaturalDocs::BinaryFile->WriteAString16( $buildTarget->Directory() );
|
||
|
NaturalDocs::BinaryFile->WriteAString16( $buildTarget->Builder()->CommandLineOption() );
|
||
|
};
|
||
|
|
||
|
NaturalDocs::BinaryFile->Close();
|
||
|
};
|
||
|
|
||
|
|
||
|
1;
|