Copy docs from C++ libloot

This commit is contained in:
Oliver Hamlet
2025-05-08 19:27:13 +01:00
parent a4ff2ba4bb
commit 7b870488c4
34 changed files with 8007 additions and 9 deletions
+4 -5
View File
@@ -275,11 +275,10 @@ endif()
install(DIRECTORY "${CMAKE_SOURCE_DIR}/include/"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# TODO: Copy across the docs into this repository?
# if(LIBLOOT_INSTALL_DOCS)
# install(DIRECTORY "${CMAKE_BINARY_DIR}/docs/html/"
# DESTINATION ${CMAKE_INSTALL_DOCDIR})
# endif()
if(LIBLOOT_INSTALL_DOCS)
install(DIRECTORY "${CMAKE_BINARY_DIR}/docs/html/"
DESTINATION ${CMAKE_INSTALL_DOCDIR})
endif()
install(EXPORT liblootTargets
FILE liblootTargets.cmake
+18 -3
View File
@@ -42,7 +42,7 @@ cmake -B build . -DCMAKE_BUILD_TYPE=Debug
cmake --build build --parallel
```
### Tests & Packaging
### Tests
The build process also builds a copy of the public API tests from C++ libloot v0.26.1 by default. To skip building the tests, pass `-DLIBLOOT_BUILD_TESTS=OFF` when first running CMake.
@@ -52,14 +52,29 @@ If built, the tests can be run using:
ctest --test-dir build --output-on-failure --parallel -V
```
### Documentation
The documentation is built using [Doxygen](http://www.stack.nl/~dimitri/doxygen/), [Breathe](https://breathe.readthedocs.io/en/latest/) and [Sphinx](http://www.sphinx-doc.org/en/stable/). Install Doxygen and Python and make sure they're accessible from your `PATH`, then run:
```
py -m venv .venv
.venv\Scripts\activate
pip install -r docs/requirements.txt
sphinx-build -b html docs build/docs/html
```
If running on Linux, replace `.venv\Scripts\activate` with `.venv/bin/activate`.
Alternatively, you can use Docker to avoid changing your development environment, by running `docker run -it --rm -v ${PWD}/docs:/docs/docs -v ${PWD}/build:/docs/build -v ${PWD}/include:/docs/include sphinxdoc/sphinx:7.3.7 bash` to obtain a shell that you can use to run `apt-get update && apt-get install -y doxygen` and then the two commands above.
### Packaging
To package the build:
```
cpack --config build/CPackConfig.cmake -C RelWithDebInfo
```
This repository (and so the created package) doesn't currently include any of libloot's documentation, besides the API documentation included in the Rust source code.
## Usage notes
For the first layer of the wrapper, built using Cargo:
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
*******
Credits
*******
libloot is written by `Ortham`_ in C++ and makes use of the `Boost`_,
`esplugin`_, `libloadorder`_, `loot-condition-interpreter`_,
`spdlog`_ and `yaml-cpp`_ libraries. The copyright licenses for all of these and
libloot itself in :doc:`../licenses/texts`.
.. _Ortham: https://github.com/Ortham
.. _Boost: http://www.boost.org/
.. _esplugin: https://github.com/Ortham/esplugin
.. _libloadorder: https://github.com/Ortham/libloadorder
.. _loot-condition-interpreter: https://github.com/loot/loot-condition-interpreter
.. _spdlog: https://github.com/gabime/spdlog
.. _yaml-cpp: https://github.com/loot/yaml-cpp
+16
View File
@@ -0,0 +1,16 @@
************
Introduction
************
LOOT is a utility that helps users avoid serious conflicts between their mods by
setting their plugins in an optimal load order. It also provides tens of
thousands of plugin-specific messages, including usage notes, requirements,
incompatibilities, bug warnings and installation mistake notifications, and
thousands of Bash Tag suggestions.
This metadata that LOOT supplies is stored in its masterlist, which is
maintained by the LOOT team using information provided by mod authors and users.
Users can also add to and modify the metadata used by LOOT through the use of
userlist files. libloot provides all of LOOT's non-UI-related functionality, and
can be used by third-party developers to access this metadata for use in their
own programs.
+93
View File
@@ -0,0 +1,93 @@
*********************
Miscellaneous Details
*********************
String Encoding
===============
* All output strings are encoded in UTF-8.
* Metadata files are written encoded in UTF-8.
* Input strings are expected to be encoded in UTF-8.
* Metadata files read are expected to be encoded in UTF-8.
* File paths are case-sensitive if and only if the underlying file system is
case-sensitive.
Language Codes
==============
All language strings in the API are codes of the form ``ll`` or ``ll_CC``, where
``ll`` is an ISO 639-1 language code and ``CC`` is an ISO 3166 country code. For
example, the default language for metadata message content is English,
identified by the code ``en``, and Brazilian Portuguese is ``pt_BR``.
Errors
======
All errors encountered are thrown as exceptions that inherit from
``std::exception``.
Metadata Files
==============
LOOT stores plugin metadata in YAML files. It distinguishes between three types
of metadata file:
- *masterlist* files: each game has a single masterlist, which is a public,
curated metadata store
- *masterlist prelude* files: there is a single masterlist prelude, which is a
public store of common metadata templates that can be shared across all
masterlists
- *userlist* files: each game has a userlist, which is a private user-specific
metadata store containing metadata added by the LOOT user.
All three files use the same syntax, but the masterlist prelude file is used to
replace part of a masterlist file before it is parsed, and metadata in the
userlist extends or replaces metadata sourced from the masterlist.
LOOT's plugin metadata can be conditional, eg. a plugin may require a patch only
if another plugin is also present. The API's
:cpp:func:`loot::DatabaseInterface::LoadLists()` method parses metadata files
into memory, but does not evaluate these conditions, so the loaded metadata may
contain metadata that is invalid for the installed game that the
:cpp:class:`loot::DatabaseInterface` object being operated on was created for.
Caching
=======
All unevaluated metadata is cached between calls to :cpp:func:`loot::DatabaseInterface::LoadLists`.
The results of evaluating metadata conditions are cached between calls to
:cpp:func:`loot::GameInterface::LoadPlugins`,
:cpp:func:`loot::GameInterface::SortPlugins` and
:cpp:func:`loot::DatabaseInterface::GetGeneralMessages`.
Plugin content is cached between calls to
:cpp:func:`loot::GameInterface::LoadPlugins` and
:cpp:func:`loot::GameInterface::SortPlugins`.
Load order is cached between calls to
:cpp:func:`loot::GameInterface::LoadCurrentLoadOrderState`.
Performance
===========
The following may involve filesystem access and reading/parsing or writing of
data from the filesystem:
- Any function that takes a ``std::filesystem::path``
- :cpp:any:`loot::GameInterface::IsValidPlugin()`
- :cpp:any:`loot::GameInterface::LoadPlugins()`
- :cpp:any:`loot::GameInterface::LoadCurrentLoadOrderState()`
- :cpp:any:`loot::GameInterface::SetLoadOrder()`
Evaluating conditions may also involve filesystem read access.
:cpp:any:`loot::GameInterface::SortPlugins()` is expensive, as it involves loading
all the content of all the plugins, apart from the game's main master file, which is skipped as an optimisation (it doesn't depend on anything else and is much bigger than any other plugin, so is unnecessary and slow to load).
:cpp:any:`loot::DatabaseInterface::GetGroupsPath()` involves building a graph of all defined groups and
then using it to search for the shortest path between the two given groups,
which may be relatively slow given a sufficiently large and/or complex set of
group definitions.
All other API functions should be relatively fast.
+115
View File
@@ -0,0 +1,115 @@
*************
API Reference
*************
.. contents::
Constants
=========
.. doxygenvariable:: loot::LIBLOOT_VERSION_MAJOR
.. doxygenvariable:: loot::LIBLOOT_VERSION_MINOR
.. doxygenvariable:: loot::LIBLOOT_VERSION_PATCH
Enumerations
============
.. doxygenenum:: loot::EdgeType
.. doxygenenum:: loot::GameType
.. doxygenenum:: loot::LogLevel
.. doxygenenum:: loot::MessageType
Functions
=========
.. doxygenfunction:: loot::SetLoggingCallback
.. doxygenfunction:: loot::SetLogLevel
.. doxygenfunction:: loot::IsCompatible
.. doxygenfunction:: loot::CreateGameHandle
.. doxygenfunction:: loot::GetLiblootVersion
.. doxygenfunction:: loot::GetLiblootRevision
.. doxygenfunction:: loot::SelectMessageContent
Interfaces
==========
.. doxygenclass:: loot::DatabaseInterface
:members:
.. doxygenclass:: loot::GameInterface
:members:
.. doxygenclass:: loot::PluginInterface
:members:
Classes
=======
.. doxygenclass:: loot::ConditionalMetadata
:members:
.. doxygenclass:: loot::Filename
:members:
.. doxygenclass:: loot::File
:members:
.. doxygenclass:: loot::Group
:members:
.. doxygenclass:: loot::Location
:members:
.. doxygenclass:: loot::MessageContent
:members:
.. doxygenclass:: loot::Message
:members:
.. doxygenclass:: loot::PluginCleaningData
:members:
.. doxygenclass:: loot::PluginMetadata
:members:
.. doxygenclass:: loot::Tag
:members:
.. doxygenclass:: loot::Vertex
:members:
Exceptions
==========
.. doxygenclass:: loot::CyclicInteractionError
:members:
.. doxygenclass:: loot::ConditionSyntaxError
:members:
.. doxygenclass:: loot::FileAccessError
:members:
.. doxygenclass:: loot::UndefinedGroupError
:members:
Error Categories
================
LOOT uses error category objects to identify errors with codes that originate in
lower-level libraries.
.. doxygenfunction:: loot::esplugin_category
.. doxygenfunction:: loot::libloadorder_category
+231
View File
@@ -0,0 +1,231 @@
************************
LOOT's Sorting Algorithm
************************
LOOT's sorting algorithm consists of the following stages:
.. contents::
:local:
Load plugin data
================
In this first stage, the plugins to be sorted are parsed and their record IDs
(which are FormIDs for all games apart from Morrowind) are stored. When parsing
plugins, all subrecords are skipped over for efficiency, apart from the
subrecords of the ``TES4`` header record, and some Morrowind plugin subrecords.
Due to how their record IDs work, Morrowind and Starfield plugins can only have
their record IDs properly understood if all of their masters can also be parsed,
so sorting will fail at this point if any Morrowind or Starfield plugin has a
master that is not installed.
Loading plugin data also involves loading any metadata that the plugin may have
in the masterlist and userlist.
Create plugin graph vertices
============================
Once the plugins have been loaded, they are sorted into lexicographical order.
This ensures that the sorting process operates on the plugins in the same order
every time, so that it gives consistent results.
After that, three graphs are created, and the plugins are added to them as
vertices in their sorted order:
- One graph contains plugins that are not masters (meaning master plugins in
their own right, not that they are listed as a master within another plugin's
header).
- One graph contains plugins that are blueprint masters: blueprint masters are
a type of plugin specific to Starfield, so for all other games this graph will
be empty.
- One graph contains plugins that are non-blueprint masters.
Three graphs are used because blueprint master plugins always load after all
other plugins and non-masters always load after non-blueprint masters (not
quite, but LOOT doesn't currently support hoisting non-masters), and it's
much more efficient to sort them separately and then combine their load orders
than to enforce those relationships within a single graph.
A consequence of using three separate graphs is that any plugin data or metadata
that involves a pair of plugins that go in different graphs will be silently
ignored. For example: if plugin A is a master and plugin B is not, and
plugin A has metadata saying it must load after plugin B, then that metadata
will be ignored because the two plugins are sorted independently, as if the
other plugin is not installed.
To help catch invalid metadata, there's also a validation step that checks for
things like requirement metadata that tries to load a blueprint master before
another plugin, and sorting will fail if any such invalid metadata is found.
A fourth graph is created to represent which groups must load after
which other groups, with groups being added in lexicographical order and
masterlist groups before userlist groups.
Create plugin graph edges
=========================
The steps described in this section are run on all graphs independently.
In this section, the terms *vertex* and *plugin* are used interchangeably, and
the iteration order 'for each plugin' is the order in which the vertices were
added to the graph.
For each plugin:
1. If the plugin is a master file, add edges going to all non-master files. If
the plugin is a non-master file, add edges coming from all master files. This
shouldn't result in any edges being added, since masters and non-masters are
sorted in separate graphs, but is done for completeness.
2. Add edges coming from all the plugin's masters. Missing masters have no edges
added.
3. Add edges coming from all the plugin's requirements. Missing requirements
have no edges added.
4. Add edges coming from all the plugin's load after files that are installed
plugins.
Hardcoded edges
---------------
Some games hardcode certain plugins to load in certain positions, and this
section adds edges in the correct order between those plugins, and between those
plugins and the rest of the plugins in the graph.
At this point the plugin graph is checked for cycles, and an error is thrown if
any are encountered, so that metadata (or indeed plugin data) that cause them
can be corrected.
Group edges
-----------
A depth-first search of the groups graph is performed for each group in the
graph, in the order that they were added to the graph, except that root vertices
go first, in descending order of their longest path length.
As the groups graph is searched, a stack of edges is used to record the current
path through the graph from the starting group. On each new edge encountered, it
is added to the stack and plugin graph edges are added going from all the
plugins in the current path's groups to the current edge's target group, except
when that would cause a cycle, and for plugins in the ``default`` group, which
are ignored. Once the graph beyond an edge's target group has been fully
explored, that edge is removed from the stack.
Once all the groups have been iterated over, one final depth-first search is
performed, this time starting from the ``default`` group and *not* skipping
edges from its plugins.
In this way all plugins have edges added from them to all the plugins in the
groups that load after their group, unless the edge would cause a cycle.
Overlap edges
-------------
Plugin overlap edges are then added. Two plugins overlap if they contain the
same record, i.e. if they both edit the same record or if one edits a record the
other plugin adds. Plugins also overlap if they both load one or more BSAs (BA2s
for Fallout 4) and the BSAs loaded by one plugin contain data for a file path
that is also included in the BSAs loaded by the other plugin.
For each plugin, skip it if it overrides no records, otherwise iterate over all
other plugins.
* If the plugin and other plugin override the same number of records and the
same number of assets, or do not overlap, skip the other plugin.
* Otherwise, add an edge from the plugin which overrides more records to the
plugin that overrides fewer records, unless that edge would cause a cycle. If
the plugins don't have overlapping records or override the same number of
records, the edge is added from the plugin that loads more assets via its
BSAs to the plugin that loads fewer assets.
For Morrowind, identifying which records override others requires all of a
plugin's masters to be installed, so if a plugin has missing masters, its total
record count is used in place of its override record count. Morrowind plugins
also can't load BSAs, so they can't have overlapping assets.
Tie-break edges
---------------
Finally, tie-break edges are added to ensure that sorting is consistent. The
graph's vertices are sorted into their current load order:
* If both plugins have positions in the current load order, the function
preserves their existing relative order.
* If one plugin has a position and the other does not, the plugin with a
position goes before the plugin without a position.
* If neither plugin has a load order position, a case-insensitive
lexicographical comparison of their filenames without file extensions is used
to decide their order. If they are equal, a case-insensitive lexicographical
comparison of their file extensions is used.
Once sorted, they are iterated over. Each loop looks at the current vertex and
the next one following it (e.g. the first iteration is for vertices 0 and 1, the
second is for 1 and 2, etc.).
For each (``current``, ``next``) pair of vertices, try to find a path from
``next`` to ``current``.
If sorting makes no changes, then there won't be any paths found and it'll
therefore be possible to add an edge from ``current`` to ``next`` without
causing a cycle, producing the old load order.
If no path is found then that means the old load order can be used for those two
plugins. If the ``current`` vertex has not already been processed (which will be
the case unless it appeared in a path found earlier and had its position pinned,
see below), append it to a list representing the new load order and record the
vertex as having been processed.
If no path is found but the ``current`` vertex has been processed and is not the
last vertex in the new load order list, pin the position of the ``next`` vertex
(see below).
If a path is found then that means the old load order for those two plugins
(which is ``current`` before ``next``) can't be used. If ``current`` is the
first vertex in the iteration order, then ``next`` is simply treated as the
start of the new load order. If ``current`` is not the first vertex,
iterate over the vertices in the path found, going from ``next`` to ``current``,
and pin each vertex's position.
Pinning vertex positions
^^^^^^^^^^^^^^^^^^^^^^^^
A vertex's position needs to be pinned when it must go somewhere before the last
plugin in the new load order list, because although it has a fixed position
relative to that last plugin, it doesn't necessarily have a fixed position
relative to the plugins that come before the last plugin. I.e. it needs to load
earlier, but how much earlier?
To pin a vertex's position, iterate over the new load order list in reverse
order, going from the last vertex towards the first, and stop at the first
load order vertex for which there is no path going from the unpinned vertex to
the load order vertex. This is equivalent to finding the last plugin that the
unpinned vertex's plugin can load after (which is not necessarily the same as
the last plugin it *must* load after).
If such a load order vertex is found, add an edge going from it to the unpinned
vertex. If the found vertex is not the last vertex in the load order list, also
add an edge going from the unpinned vertex to the vertex after the found vertex.
Then record the unpinned vertex's new position in the new load order list: the
vertex is now pinned.
Topologically sort the plugin graphs
====================================
This is done for all graphs independently.
Note that edges for explicit interdependencies are the only edges allowed to
create cycles. However, the graph is again checked for cycles to guard against
potential logic bugs, and if a cycle is encountered an error is thrown.
Once the graph is confirmed to be cycle-free, a topological sort is performed on
the graph, outputting a list of plugins in their newly-sorted load order.
Combine the load orders
=======================
Finally, the sorted load orders are combined in this order:
1. master plugins
2. non-master plugins
3. blueprint master plugins
That gives the complete sorted load order.
+356
View File
@@ -0,0 +1,356 @@
# -*- coding: utf-8 -*-
#
# LOOT documentation build configuration file, created by
# sphinx-quickstart on Sat Aug 13 21:09:25 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import subprocess, os
output_directory = os.path.join('..', 'build', 'docs')
if not os.path.exists(output_directory):
os.makedirs(output_directory)
subprocess.call(['doxygen', 'docs/api/Doxyfile'], cwd='..')
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'breathe',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'libloot'
copyright = u'2016, WrinklyNinja'
author = u'WrinklyNinja'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'latest'
# The full version, including alpha/beta/rc tags.
release = u'latest'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#
# today = ''
#
# Else, today_fmt is used as the format for a strftime call.
#
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u''
# A shorter title for the navigation bar. Default is the same as html_title.
#
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#
# html_additional_pages = {}
# If false, no module index is generated.
#
# html_domain_indices = True
# If false, no index is generated.
#
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'LOOTdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'libloot.tex', u'libloot Documentation',
u'WrinklyNinja', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#
# latex_use_parts = False
# If true, show page references after internal links.
#
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#
# latex_appendices = []
# It false, will not define \strong, \code, itleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated.
#
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'libloot', u'libloot Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'libloot', u'libloot Documentation',
author, 'libloot', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#
# texinfo_appendices = []
# If false, no module index is generated.
#
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#
# texinfo_no_detailmenu = False
breathe_projects = {
"loot":"../build/docs/xml/",
}
breathe_default_project = 'loot'
+30
View File
@@ -0,0 +1,30 @@
#######
libloot
#######
.. toctree::
:maxdepth: 2
:caption: API Documentation
api/introduction
api/miscellaneous
api/sorting
api/reference
api/credits
api/changelog
.. toctree::
:maxdepth: 2
:caption: Metadata Syntax Documentation
metadata/introduction
metadata/file_structure
metadata/data_structures/index
metadata/conditions
metadata/changelog
.. toctree::
:caption: Copyright Licenses
licenses/notice.rst
licenses/texts.rst
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+423
View File
@@ -0,0 +1,423 @@
GNU Free Documentation License
Version 1.3, 3 November 2008
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
<http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The "Document", below,
refers to any such manual or work. Any member of the public is a
licensee, and is addressed as "you". You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall
subject (or to related matters) and contains nothing that could fall
directly within that overall subject. (Thus, if the Document is in
part a textbook of mathematics, a Secondary Section may not explain
any mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
The "publisher" means any person or entity that distributes copies of
the Document to the public.
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document. These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no
other conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to
give them a chance to provide you with an updated version of the
Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct
from that of the Document, and from those of previous versions
(which should, if there were any, be listed in the History section
of the Document). You may use the same title as a previous version
if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
Document (all of its principal authors, if it has fewer than five),
unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
giving the public permission to use the Modified Version under the
terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
there is no section Entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
public access to a Transparent copy of the Document, and likewise
the network locations given in the Document for previous versions
it was based on. These may be placed in the "History" section.
You may omit a network location for a work that was published at
least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.
K. For any section Entitled "Acknowledgements" or "Dedications",
Preserve the Title of the section, and preserve in the section all
the substance and tone of each of the contributor acknowledgements
and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements". Such a section
may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements"
or to conflict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications". You must delete all sections
Entitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other
documents released under this License, and replace the individual
copies of this License in the various documents with a single copy
that is included in the collection, provided that you follow the rules
of this License for verbatim copying of each of the documents in all
other respects.
You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert a
copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that
document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, or distribute it is void, and
will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, receipt of a copy of some or all of the same material does
not give you any rights to use it.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of the
GNU Free Documentation License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation. If the Document
specifies that a proxy can decide which future versions of this
License can be used, that proxy's public statement of acceptance of a
version permanently authorizes you to choose that version for the
Document.
11. RELICENSING
"Massive Multiauthor Collaboration Site" (or "MMC Site") means any
World Wide Web server that publishes copyrightable works and also
provides prominent facilities for anybody to edit those works. A
public wiki that anybody can edit is an example of such a server. A
"Massive Multiauthor Collaboration" (or "MMC") contained in the site
means any set of copyrightable works thus published on the MMC site.
"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
license published by Creative Commons Corporation, a not-for-profit
corporation with a principal place of business in San Francisco,
California, as well as future copyleft versions of that license
published by that same organization.
"Incorporate" means to publish or republish a Document, in whole or in
part, as part of another Document.
An MMC is "eligible for relicensing" if it is licensed under this
License, and if all works that were first published under this License
somewhere other than this MMC, and subsequently incorporated in whole or
in part into the MMC, (1) had no cover texts or invariant sections, and
(2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site
under CC-BY-SA on the same site at any time before August 1, 2009,
provided the MMC is eligible for relicensing.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Gabi Melman.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,19 @@
Copyright (c) 2008 Jesse Beder.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+17
View File
@@ -0,0 +1,17 @@
****************
Copyright Notice
****************
LOOT and its API are distributed under the GNU General Public License v3.0. The documentation is distributed under the GNU Free Documentation License v1.3. The full texts of both licenses are included in :doc:`../licenses/texts`.
While the GPL license allows anyone to make derivative works of LOOT, the LOOT Team encourages those thinking of doing so to first discuss their reasoning for such an endeavour with the Team. It may be that what the derivative work would do differently is already planned for a future version of LOOT or would be happily integrated into LOOT, thus avoiding any extra effort by others.
LOOT has been specifically designed to prevent it being locked into the LOOT Team's official masterlist repositories. Nevertheless, the LOOT Team appeals to the community to avoid the distribution of unofficial masterlists, as this would only hamper the effort to create one set of stores for load order information. Any issues with a masterlist are best brought to the attention of the LOOT Team so that they may be remedied.
GNU Free Documentation License Version 1.3 Notice:
Copyright (C) 2012—2016 WrinklyNinja
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in :doc:`../licenses/texts`.
+44
View File
@@ -0,0 +1,44 @@
***********************
Copyright License Texts
***********************
.. contents::
`Boost`_
========
.. _Boost: http://www.boost.org/
.. include:: Boost Software License v1.0.txt
:literal:
libloot, `esplugin`_ & `Libloadorder`_
======================================
.. _esplugin: https://github.com/Ortham/esplugin
.. _libloadorder: https://github.com/Ortham/libloadorder
.. include:: GNU GPL v3.txt
:literal:
libloot Documentation
======================
.. include:: GNU FDL v1.3.txt
:literal:
`spdlog`_
============
.. _spdlog: https://github.com/gabime/spdlog
.. include:: MIT License (spdlog).txt
:literal:
`yaml-cpp`_
===========
.. _yaml-cpp: https://github.com/loot/yaml-cpp
.. include:: MIT License (yaml-cpp).txt
:literal:
+253
View File
@@ -0,0 +1,253 @@
***************
Version History
***************
The version history of the metadata syntax is given below.
0.26 - 2025-04-19
=================
Added
-----
- The ``File`` data structure now has a ``constraint`` key that takes a
condition string that must evaluate to true for the file's existence to be
recognised.
- The ``file_size(file_path path, file_size size)`` condition function, which
returns true if the given file's size matches the given number of bytes, and
false otherwise (including if the file doesn't exist).
- The ``filename_version(regular_expression path, version given_version, comparison_operator comparator)``
condition function, which takes a regex path with a single capture group, a
version string and a comparison operator and returns true if there is a path
that matches the regex path and the value captured by the regex is a version
string for which the comparison against the given version is true. Unlike the
other version functions, it always returns false if it cannot find a version
to compare against the given version, irrespective of the given comparison
operator.
- The ``description_contains(file_path path, regular_expression regex)``
condition function, which takes a path and a regex and returns true if the
given path is a plugin with a description that contains text that matches the
given regex, and false otherwise (including if the path does not exist, is not
a plugin, or has no description).
- The ``is_executable(file_path path)`` condition function, which returns true
if the given path is a Windows executable (PE) file.
Changed
-------
- Line breaks are now accepted as whitespace when parsing condition strings, so
long expressions can be split over multiple lines.
0.21 - 2023-08-30
=================
Changed
-------
- The syntax for substitution placeholders is now zero-indexed and uses curly
braces instead of percentage signs. For example, ``%1% %2%`` is now
``{0} {1}``.
Removed
-------
- Support for the ``LOOT`` file path alias. It will now be interpreted as a
normal path, i.e. a file or folder named ``LOOT`` in the game's data path.
0.18 - 2022-02-27
=================
Added
-----
- The condition function ``readable(filesystem_path path)``, which checks if
the given path is a readable directory or file.
Changed
-------
- The documentation for the version comparison condition functions has been
updated to detail the supported version syntax and semantics.
- Mentions of GitHub Flavored Markdown have been replaced with CommonMark, as
LOOT now uses the latter instead of the former.
Fixed
-----
- Support for ``not (<expression>)`` syntax was not properly documented.
- The documentation for the version comparison functions stated that missing
versions would be treated as if they were ``0``, which was not accurate.
0.17 - 2021-09-24
=================
Added
-----
- The ``File`` data structure now has a ``detail`` key that takes a string or
localised content list.
- The top-level ``prelude`` key can be used to supply common data structure
definitions, and in masterlists its value is replaced by the contents of the
masterlist prelude file, if present.
- Support for parsing inverted metadata conditions (``not (<expression>)``).
Changed
-------
- The cleaning data structure's ``info`` key has been renamed to ``detail`` for
consistency.
0.16 - 2020-07-12
=================
Changed
-------
- Equality for all metadata data structures is now determined by comparison of
all their fields. String comparison is case-sensitive, with the exception of
``File``'s ``name`` field.
Removed
-------
- The ``enabled`` field has been removed from plugin metadata objects.
0.15 - 2019-11-05
=================
Added
-----
- The condition function ``is_master(file_path path)``, which checks if the
given file is an installed master plugin.
0.14 - 2018-12-09
=================
Added
-----
- The ``Group`` data structure now has a ``description`` key that takes a string
value.
- The condition function ``product_version(file_path path, version
given_version, comparison_operator comparator)``, which checks against the
Product Version field of an executable.
Changed
-------
- ``clean`` and ``dirty`` metadata are now allowed in regex plugin entries.
- ``Location``, ``Message``, ``MessageContent`` and ``Tag`` equality comparisons
are now case-sensitive.
- Regular expressions in condition strings now use a `modified Perl grammar`_
instead of a modified ECMAScript grammar. ``Plugin`` object ``name`` fields
still use the modified ECMAScript grammar for regex values. To improve
portability and avoid mistakes, it's best to stick to using the subset of
regular expression features that are common to both grammars.
Removed
-------
- The change in regular expression grammar means that the following regular
expression features are no longer supported in condition strings:
- ``\c<letter>`` control code escape sequences, use ``\x<hex>`` instead
- The ``\0`` null escape sequence, - use ``\x00`` instead
- The ``[:d:]``, ``[:w:]`` and ``[:s:]`` character classes,
use ``[:digit:]``, ``[:alnum:]`` and ``[:space:]`` instead respectively.
- ``\<number>`` backreferences
- ``(?=<subpattern>)`` and ``(?!<subpattern>)`` positive and negative lookahead
.. _modified Perl grammar: https://docs.rs/regex/1.0.5/regex/index.html#syntax
0.13 - 2018-04-02
=================
Added
-----
- The ``Group`` data structure.
- The ``groups`` list to the root of the metadata file format.
- The ``group`` key to the plugin data structure.
Removed
-------
- The ``priority`` field from the plugin data structure.
- The ``global_priority`` field from the plugin data structure.
0.10 - 2016-11-06
=================
Added
-----
* The ``clean`` key to the plugin data structure.
* The ``global_priority`` field to the plugin data structure.
* The ``many_active()`` condition function.
* The ``info`` key to the cleaning data structure.
Changed
-------
* Renamed the ``str`` key in the localised content data structure to ``text`` .
* The ``priority`` field of the plugin data structure now stores values between -127 and 127 inclusive.
* Regular expressions no longer accept ``\`` as a directory separator: ``/`` must now be used.
* The ``file()`` condition function now also accepts a regular expression.
* The ``active()`` condition function to also accept a regular expression.
* Renamed the dirty info data structure to the cleaning data structure.
Removed
-------
* The ``regex()`` condition function, as it has been obsoleted by the ``file()`` function's new regex support.
0.8 - 2015-07-22
================
Added
-----
* The ``name`` key to the location data structure.
* The ``many("regex")`` condition function.
* The documentation now defines the equality criteria for all of the metadata syntax's non-standard data structures.
Changed
-------
* Detection of regular expression plugin entries. Previously, a plugin entry was treated as having a regular expression filename if the filename ended with ``\.esp`` or ``\.esp`` . Now, a plugin entry is treated as having a regular expression filename if the filename contains one or more of ``:\*?|`` .
Removed
-------
* Removed the ``ver`` key in the location data structure.
Fixed
-----
* The documentation gave the values of the ``after`` , ``req`` , ``inc`` , ``tag`` , ``url`` and ``dirty`` keys as lists, when they have always been sets.
0.7 - 2015-05-20
================
Added
-----
* The message string substitution key, i.e. ``sub`` , in the message data structure.
* Support for YAML merge keys, i.e. ``<<`` .
Changed
-------
* Messages may now be formatted using most of GitHub Flavored Markdown, minus the GitHub-specific features (like @mentions, issue/repo linking and emoji).
0.6 - 2014-07-05
================
No changes.
0.5 - 2014-03-31
================
Initial release.
+298
View File
@@ -0,0 +1,298 @@
*****************
Condition Strings
*****************
Condition strings can be used to ensure that data is only acted on by LOOT under certain circumstances. They are very similar to boolean conditional expressions in programming languages such as Python, though more limited.
Omitting optional parentheses (see below), their `EBNF`_ grammar is:
.. productionlist::
expression: condition, { logical_or, compound_condition }
compound_condition: condition, { logical_and, condition }
condition: ( [ logical_not ], function ) | ( [ logical_not ], "(", expression, ")" )
logical_and: "and"
logical_or: "or"
logical_not: "not"
.. _EBNF: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form
Spaces, tabs, carriage returns and line feeds (i.e. line breaks) can be used on either side of:
- ``logical_and``, as defined above
- ``logical_or``, as defined above
- ``logical_not``, as defined above
- parentheses around conditions and expressions
- commas separating function arguments
Types
=====
.. describe:: filesystem_path
A double-quoted filesystem path.
.. describe:: file_path
A double-quoted file path.
.. describe:: file_size
A string of decimal digits representing an unsigned integer number of bytes.
.. describe:: regular_expression
A double-quoted file path, with a regular expression in place of a filename. The path must use ``/`` for directory separators, not ``\``. The regular expression must be written in a `modified Perl <https://docs.rs/regex/1.0.5/regex/index.html#syntax>`_ syntax.
Only the filename path component will be evaluated as a regular expression. For example, given the regex file path ``Meshes/Resources(1|2)/(upperclass)?table.nif``, LOOT will look for a file named ``table.nif`` or ``upperclasstable.nif`` in the ``Meshes\Resources(1|2)`` folder, rather than looking in the ``Meshes\Resources1`` and ``Meshes\Resources2`` folders.
.. describe:: checksum
A string of hexadecimal digits representing an unsigned integer that is the data checksum of a file. LOOT displays the checksums of plugins in its user interface after running.
.. describe:: version
A double-quoted string of characters representing the version of a plugin or executable. LOOT displays the versions of plugins in its user interface after running.
.. describe:: comparison_operator
One of the following comparison operators.
.. describe:: ==
Is equal to
.. describe:: !=
Is not equal to
.. describe:: <
Is less than
.. describe:: >
Is greater than
.. describe:: <=
Is less than or equal to
.. describe:: >=
Is greater than or equal to
Functions
=========
There are several conditions that can be tested for using the functions detailed below. All functions return a boolean. For functions that take a path or regex, the argument is treated as regex if it contains any of the characters ``:\*?|``.
.. describe:: file(filesystem_path path)
Returns true if ``path`` is installed, and false otherwise.
.. describe:: file(regular_expression regex)
Returns true if a file matching ``regex`` is found, and false otherwise.
.. describe:: file_size(file_path path, file_size size)
Returns true if the file at the given ``path`` has the given ``size``, and
false otherwise.
.. describe:: readable(filesystem_path path)
Returns true if ``path`` is a readable directory or file, and false otherwise.
This is particularly useful when writing conditions for games that are available from the Microsoft Store and/or Xbox app, as games installed using them have executables that have heavily restricted permissions, and attempts to read them result in permission denied errors. You can use this function to guard against such errors by calling it before the ``checksum``, ``version`` or ``product_version`` functions.
.. describe:: active(file_path path)
Returns true if ``path`` is an active plugin, and false otherwise.
.. describe:: active(regular_expression regex)
Returns true if an active plugin matching ``regex`` is found, and false otherwise.
.. describe:: many(regular_expression regex)
Returns true if more than one file matching ``regex`` is found, and false otherwise.
.. describe:: many_active(regular_expression regex)
Returns true if more than one active plugin matching ``regex`` is found, and false otherwise.
.. describe:: is_master(file_path path)
Returns true if ``path`` is an installed master plugin, and false otherwise. This returns false for all OpenMW plugins, as OpenMW does not force master plugins to load before others.
.. describe:: is_executable(file_path path)
Returns true if ``path`` is a Windows executable (PE) file, and false
otherwise.
.. describe:: checksum(file_path path, checksum expected_checksum)
Returns true if the calculated CRC-32 checksum of ``path`` matches ``expected_checksum``, and false otherwise. Returns false if ``path`` does not exist.
.. describe:: version(file_path path, version given_version, comparison_operator comparator)
Returns true if the boolean expression::
actual_version comparator given_version
(where ``actual version`` is the version read from ``path``) holds true, and
false otherwise.
* If ``path`` is a plugin, its version is read from its description field.
* If ``path`` is not a plugin, it will be assumed to be an executable (e.g.
``*.exe`` or ``*.dll``), and its version is read from its File Version field.
* If ``path`` does not exist or does not have a version number, the condition
evaluates to true for the ``!=``, ``<`` and ``<=`` comparators, i.e. a
missing version is always less than the given version.
* If ``path`` is not readable or is not a plugin or an executable, an error
will occur.
The supported version syntax and precedence rules are detailed in the section
below.
.. describe:: product_version(file_path path, version given_version, comparison_operator comparator)
Returns true if the boolean expression::
actual_version comparator given_version
(where ``actual version`` is the version read from ``path``) holds true, and
false otherwise. ``path`` must be an executable (e.g. ``*.exe`` or ``*.dll``),
and its version is read from its Product Version field.
* If ``path`` does not exist or does not have a version number, the condition
evaluates to true for the ``!=``, ``<`` and ``<=`` comparators, i.e. a
missing version is always less than the given version.
* If ``path`` is not a readable executable, an error will occur.
The supported version syntax and precedence rules are detailed in the section
below.
.. describe:: filename_version(regular_expression path, version given_version, comparison_operator comparator)
The regex in ``path`` must contain a single capturing group.
Returns true if a file matching ``path`` is found for which the boolean
expression::
actual_version comparator given_version
(where ``actual_version`` is the value captured by the regex) holds true, and
false otherwise.
Unlike the other version functions, it always returns false if it cannot find
a version to compare against the given version, irrespective of the given
comparison operator.
.. describe:: description_contains(file_path path, regular_expression regex)
Returns true if ``path`` is a plugin file with a description that contains
text that matches ``regex``, and false otherwise (including if the path does
not exist, is not a plugin, or has no description).
Version Syntax & Comparison Rules
---------------------------------
Version parsing and comparison is compatible with
`Semantic Versioning <http://semver.org/>`_, with the following exceptions:
* Pre-release identifiers may not include hyphens (``-``), as they are treated
as separators. For example, a SemVer-compliant parser would treat
``1.0.0-alpha.1.x-y-z.--`` as ``([1, 0, 0], ["alpha", 1, "x-y-z", "--"])`` but
libloot treats it as ``([1, 0, 0], ["alpha", 1, "x", "y", "z", "", ""])``.
* Identifiers that contain non-digit characters are lowercased before being
compared lexically, so that their comparison is case-insensitive instead of
case-sensitive. For example, SemVer specifies that ``1.0.0-alpha`` is greater
than ``1.0.0-Beta``, but libloot compares them with the opposite result.
These exceptions are necessary to support an extended range of real-world
versions that do not conform to SemVer. The supported extensions are:
* Leading zeroes are allowed and ignored in major, minor and patch version
numbers and numeric pre-release IDs. For example, ``01.02.03`` and ``1.2.3``
are equal.
* An arbitrary number of version numbers is allowed. To support this, the major,
minor and patch version numbers are treated as a sequence of numeric release
IDs, and any subsequent version numbers are just additional release IDs that
get appended to the sequence. For example, ``1.2.3`` may be represented as the
sequence ``[1, 2, 3]``, and ``1.2.3.4`` would be represented as
``[1, 2, 3, 4]``.
If two versions with a different number of release identifiers are compared,
the version with fewer release identifiers is padded with zero values until
they are the same length. Each release identifier in one version is then
compared against the release identifier in the same position in the other
version. For example, ``1-beta`` is padded to ``1.0.0-beta`` before being
compared against ``1.0.1-beta``, and the result is that ``1.0.1-beta`` is
greater than ``1-beta``.
* Release IDs may be separated by a period (``.``) or a comma (``,``). For
example, ``1.2.3.4`` and ``1,2,3,4`` are equal.
* The separator between release IDs and pre-release IDs may be a hyphen (``-``),
a space (" "), a colon (``:``) or an underscore (``_``). For example,
``1.2.3-alpha``, ``1.2.3 alpha``, ``1.2.3:alpha`` and ``1.2.3_alpha`` are all
equal.
* Pre-release IDs may be separated by a period (``.``), a hyphen (``-``), a
space (" "), a colon (``:``) or an underscore (``_``). For example,
``1.2.3-alpha.1``, ``1.2.3-alpha-1``, ``1.2.3-alpha 1``, ``1.2.3-alpha:1`` and
``1.2.3-alpha_1`` are all equal.
* Non-numeric release IDs are allowed. A non-numeric release ID may contain any
character (not just ASCII characters) that is not one of the separators listed
above or a plus sign (``+``). For example, ``0.78b.1`` is allowed.
Non-numeric release IDs use the same comparison rules as non-numeric
pre-release IDs, with the exception that a non-numeric release ID is not
always greater than a numeric release ID:
* If the non-numeric release ID has no leading digits, it is greater than the
numeric release ID. For example, ``1.A`` is greater than ``1.1``.
* If the non-numeric release ID has leading digits, they are parsed as a
number, and this is compared against the numeric release ID:
* If the two numbers are equal then the non-numeric release ID is greater
than the numeric release ID. For example, ``1.1A`` is greater than
``1.1``.
* Otherwise, the result of comparing the two numbers is used as the result
of comparing the two release IDs. For example, ``1.2`` is greater than
``1.1A`` and ``1.1A`` is greater than ``1.0``.
* Pre-release IDs may contain any character (not just ASCII characters) that is
not one of the pre-release ID separators listed above or a plus sign (``+``).
* Before non-numeric IDs (release or pre-release) are compared, they are
lowercased according to Unicode's lowercasing rules.
* As a special case, version strings that are four comma-and-space-separated
sequences of digits are interpreted as if the comma-and-space separators were
periods (``.``). For example, ``0, 2, 0, 12`` and ``0.2.0.12`` are equal.
Logical Operators
=================
The ``and``, ``or`` and ``not`` operators have their usual definitions.
Order of Evaluation
-------------------
Condition strings are evaluated according to the usual C-style operator precedence rules, and parentheses can be used to override these rules. For example::
function and function or not function
is evaluated as::
( function and function ) or ( not function )
but::
function and ( function or not function )
is evaluated as::
function and ( function or ( not function ) )
Performance
===========
LOOT caches the results of condition evaluations. A regular expression check will still take longer than a file check though, so use the former only when appropriate to do so.

Some files were not shown because too many files have changed in this diff Show More