\ProvidesPackage{changelog}[2019/04/15 2.0.0 Typesetting changelogs]
% Description: Provides the changelog environment for typesetting changelogs
% License:     LPPL 1.3c
% Homepage:    https://github.com/9999years/latex-changelog
%              https://ctan.org/pkg/changelog
% Maintainer:  Rebecca Turner <637275@gmail.com>
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Rebecca Turner <637275@gmail.com>.
%
% This work consists of the files changelog.sty and changelog.tex.

\RequirePackage{xparse}
\RequirePackage{xkeyval}

\newif\ifchangelog@versionfirst
\newcommand{\changelog@item}[1]{%
	\noindent
	\ifchangelog@versionfirst
		\changelog@versionfirstfalse
	\else
		\end{changelogitemize}
	\fi
	\textbf{#1}%
	\begin{changelogitemize}%
}

\newcommand{\changelogyanked}{\fbox{\textbf{YANKED}}}

\newcommand{\changelog@sectioncmds}{
	\newcommand{\added}     {\changelog@item{Added}}
	\newcommand{\changed}   {\changelog@item{Changed}}
	\newcommand{\deprecated}{\changelog@item{Deprecated}}
	\newcommand{\removed}   {\changelog@item{Removed}}
	\newcommand{\fixed}     {\changelog@item{Fixed}}
	\newcommand{\security}  {\changelog@item{Security}}
	\newcommand{\misc}      {\changelog@item{Miscellaneous}}
}

\define@cmdkeys{version}{author, version, date, changes}
\define@key{version}{v}{\def\cmdKV@version@version{#1}}
\define@boolkey{version}{yanked}[true]{}
\define@boolkey{version}{simple}[true]{}
\define@boolkey{version}{short}[true]{}

\define@cmdkeys{changelog}{sectioncmd, title, label}
\define@boolkey{changelog}{section}[true]{}
\presetkeys{changelog}{sectioncmd=\section, title=Changelog,
	label=sec:changelog, section}{}

\newenvironment{changelogdescription}
	{\begin{description}}
	{\end{description}}
\newenvironment{changelogitemize}
	{\begin{itemize}}
	{\end{itemize}}

\newcommand{\changelog@section@maybe}{%
	\ifKV@changelog@section
		\expandafter\cmdKV@changelog@sectioncmd{\cmdKV@changelog@title}%
		\expandafter\label{\cmdKV@changelog@label}%
	\fi
}

\newcommand{\changelog@shortversion@definedate}{%
	\@ifundefined{cmdKV@version@version}{
		\@ifundefined{cmdKV@version@date}{
			\newcommand{\cmdKV@version@version}{Unreleased}
			\let\cmdKV@version@date\today
		}{%
			\let\cmdKV@version@version\cmdKV@version@date
			\let\cmdKV@version@date\undefined
		}%
	}{}%
}

\newcommand{\changelog@yanked@maybe}
	{\ifKV@version@yanked\ \changelogyanked\fi}

\newcommand{\changelog@shortversion@item}
	{\cmdKV@version@version
	\changelog@yanked@maybe}


\newcommand{\changelog@shortversion@authordate}{%
	\@ifundefined{cmdKV@version@author}{}{\cmdKV@version@author}
	\@ifundefined{cmdKV@version@date}{%
		% if both undefined, add a linebreak
		\@ifundefined{cmdKV@version@author}{\hspace{0pt}}{}%
	}{(\cmdKV@version@date)}%
}

\newcommand{\changelog@version@pre}{%
	\par
	\changelog@versionfirsttrue
	\changelog@sectioncmds
	\ifKV@version@simple
		\begin{changelogitemize}
	\fi
}
\newcommand{\changelog@version@post}{%
	\ifchangelog@versionfirst
		\ifKV@version@simple
		\else
			\PackageError{changelog}{Something's wrong in version environment;
			perhaps a missing \protect\added, \protect\changed,
			\protect\deprecated, \protect\removed, \protect\fixed,
			\protect\security, or \protect\misc}{A version environment needs to
			introduce its \protect\item-ized lists with one of the provided
			section commands; maybe you meant to use the [simple] option?}
		\fi
	\fi
	\end{changelogitemize}%
}

\newif\ifchangelog@hadversion
\NewDocumentEnvironment{changelog}{o}
	{\global\changelog@hadversionfalse
	\IfValueT{#1}{\setkeys{changelog, version}{#1}}%
	\changelog@section@maybe
	%\today
	% version environment; wraps a list
	\NewDocumentEnvironment{version}{ O{} }%
		{\setkeys{version}{##1}%
		\@shortversion
		\ifKV@version@short
		\else
			\changelog@version@pre
		\fi}
		{\ifKV@version@short
		\else
			\changelog@version@post
		\fi}%

	% doesn't set keys so this can share code with the version
	% environment
	\NewDocumentCommand{\@shortversion}{}{%
		\changelog@shortversion@definedate
		\global\changelog@hadversiontrue
		\item[\changelog@shortversion@item]%
		\changelog@shortversion@authordate
		\ifKV@version@short
			\ ---
			\@ifundefined{cmdKV@version@changes}{}{\cmdKV@version@changes}%
		\fi
	}%

	% short version; "like" a 1-bullet list
	% extra braces keep command definitions local
	\NewDocumentCommand{\shortversion}{m}{{%
		\setkeys{version}{##1, short}%
		\@shortversion
	}}%
	\begin{changelogdescription}}
	{\ifchangelog@hadversion
	\else
		\PackageError{changelog}{No versions in changelog environment body}{A
		changelog environment must have at least one version or shortversion in
		it.}%
	\fi\end{changelogdescription}}
