%%
%% This is file `wtref.sty'.
%%
%% Copyright 2016-2023 Takuto Asakura (wtsnjp)
%%   GitHub:   https://github.com/wtsnjp
%%   Twitter:  @wtsnjp
%%
%% This package is distributed under the MIT License.
%%

% Package declaration
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{wtref}
  [2023/12/24 v1.0.0 A small extension for LaTeX2e's cross-referencing]
\def\wtrf@pkgname{WTRef}
\RequirePackage{xparse,xkeyval}

% Messages
\def\wtrf@info{\PackageInfo\wtrf@pkgname}
\def\wtrf@warn{\PackageWarningNoLine\wtrf@pkgname}
\def\wtrf@error{\PackageError\wtrf@pkgname}

% New ifs and counts
\newif\if@wtrf@use@scope@
\newif\if@wtrf@use@namespace@
\newif\if@wtrf@set@namespace@

% Utilities
\def\wtrf@name@def#1{\expandafter\def\csname #1\endcsname}
\def\wtrf@name@edef#1{\expandafter\edef\csname #1\endcsname}
\def\wtrf@name@use#1{\csname #1\endcsname}
\def\wtrf@if@reftype@not@exists#1{\@ifundefined{wtrf@#1@namespace}}

% Check commands
\def\wtrf@check@counter#1{%
  \@ifundefined{c@#1}{%
    \wtrf@error
      {Undefined LaTeX counter `#1'}
      {Check the spelling or declare new LaTeX counter}%
  }{}}
\def\wtrf@check@command#1{%
  \@ifundefined{#1}{}{% else
    \wtrf@warn{Redefining \expandafter\string\csname #1\endcsname}}}

% Trimming spaces
\@tempcnta=\catcode`\Q
\catcode`\Q=3
\def\wtrf@trim@spaces#1{%
  \romannumeral-`>\wtrf@trim@trim@\noexpand#1Q Q}
\long\def\wtrf@trim@trim@#1 Q{\wtrf@trim@trim@@#1Q}
\long\def\wtrf@trim@trim@@#1Q#2{#1}
\catcode`\Q=\@tempcnta
\def\wtrf@trim@spaces@noexp#1{%
  \unexpanded\expandafter\expandafter\expandafter
    {\wtrf@trim@spaces{#1}}}
\def\wtrf@trim@spaces@in#1{%
  \edef#1{\expandafter\wtrf@trim@spaces@noexp\expandafter{#1}}}

% Define keys for \newref command
\define@key[wtrf]{ns}{namespace}{%
  \@wtrf@set@namespace@true
  \def\wtrf@namespace@temp{#1}}
\define@key[wtrf]{ns}{nonamespace}[\@empty]{%
  \@wtrf@use@namespace@false}
\define@key[wtrf]{ns}{scope}{%
  \wtrf@check@counter{#1}%
  \@wtrf@use@scope@true
  \def\wtrf@scope@temp{#1}}

% Defining the \newref command
\NewDocumentCommand{\newref}{om}{%
  \let\wtrf@namespace@temp\@empty
  \@wtrf@use@namespace@true
  \@wtrf@set@namespace@false
  \@wtrf@use@scope@false
  \IfNoValueF{#1}{\setkeys[wtrf]{ns}{#1}}%
  \wtrf@@newref{#2}}
\@onlypreamble\newref
\def\wtrf@@newref#1{%
  \@for\wtrf@temp@ref@type:=#1\do{%
    \wtrf@trim@spaces@in\wtrf@temp@ref@type
    \expandafter\wtrf@newref@pre\expandafter{\wtrf@temp@ref@type}}}
\def\wtrf@newref@pre#1{%
  \wtrf@if@reftype@not@exists{#1}{%
    \wtrf@newref{#1}%
  }{% else
    \wtrf@error
      {ref type `#1' already exists}
      {You can declare ref type only once}%
  }}
\def\wtrf@newref#1{%
  % namespace
  \if@wtrf@use@namespace@
    \ifx\wtrf@namespace@temp\@empty
      \@wtrf@set@namespace@false
      \def\wtrf@namespace@temp{#1}%
    \fi
    \wtrf@name@edef{wtrf@#1@namespace}{\wtrf@namespace@temp:}%
  \else
    \wtrf@name@def{wtrf@#1@namespace}{}%
  \fi
  % scope
  \if@wtrf@use@scope@
    \wtrf@name@edef{wtrf@#1@scope@cmd}{the\wtrf@scope@temp}%
    \wtrf@name@def{wtrf@#1@scope}{\csname\wtrf@name@use{wtrf@#1@scope@cmd}\endcsname:}%
  \else
    \wtrf@name@def{wtrf@#1@scope}{}%
  \fi
  % define keys for setting styles
  \define@key[wtrf]{#1-style}{refcmd}{\wtrf@name@def{wtrf@#1@refcmd}####1{##1}}%
  \define@key[wtrf]{#1-style}{last sep}[\wtrf@name@use{wtrf@#1@sep}]{%
    \wtrf@name@def{wtrf@#1@last@sep}{##1}}%
  \define@cmdkeys[wtrf]{#1-style}[wtrf@#1@]{sep, prefix, suffix}%
  % default key settings
  \setkeys[wtrf]{#1-style}{%
    refcmd=\ref{##1},
    sep={,\space}, last sep,
    prefix={}, suffix={}}%
  % the \label-like command
  \wtrf@check@command{#1label}%
  \expandafter\DeclareExpandableDocumentCommand\csname #1label\endcsname{m}{%
    \expandafter\expandafter\expandafter\label\expandafter\expandafter\expandafter
      {\csname wtrf@#1@namespace\expandafter\endcsname
       \romannumeral-`>\csname wtrf@#1@scope\endcsname ##1}}%
  % the \ref-like command
  \wtrf@check@command{#1ref}%
  \expandafter\DeclareExpandableDocumentCommand\csname #1ref\endcsname{om}{%
    \if@wtrf@use@scope@
      \IfNoValueTF{##1}
        {\wtrf@name@use{wtrf@#1ref}{\wtrf@name@use{wtrf@#1@scope}}{##2}}
        {\wtrf@name@use{wtrf@#1ref}{##1:}{##2}}%
    \else
      \wtrf@name@use{wtrf@#1ref}{}{##2}%
    \fi}
  % construction
  \wtrf@name@def{wtrf@#1ref}##1##2{%
    \wtrf@name@use{wtrf@#1@prefix}%
    \wtrf@construct##2,\wtrf@qmark\wtrf@nil{##1}{#1}%
    \wtrf@name@use{wtrf@#1@suffix}}
  % reset \wtrf@namespace@temp
  \if@wtrf@set@namespace@\else
    \let\wtrf@namespace@temp\@empty
  \fi}

% The constructer for \ref-like commands
\def\wtrf@qmark{\wtrf@qmark}
\def\wtrf@head#1#2\wtrf@nil{#1}
%% \wtrf@construct<head>,<rest>\wtrf@nil{<scope>}{<ref type>}
\def\wtrf@construct#1,#2\wtrf@nil#3#4{%
  \wtrf@name@use{wtrf@#4@refcmd}{%
    \wtrf@name@use{wtrf@#4@namespace}#3\wtrf@trim@spaces@noexp{#1}}%
  \expandafter\ifx\wtrf@head#2\wtrf@nil\wtrf@qmark\else
    \wtrf@construct@#2\wtrf@nil{#3}{#4}%
  \fi}
\def\wtrf@construct@#1,#2\wtrf@nil#3#4{%
  \expandafter\ifx\wtrf@head#2\wtrf@nil\wtrf@qmark
    \wtrf@name@use{wtrf@#4@last@sep}%
    \wtrf@name@use{wtrf@#4@refcmd}{%
      \wtrf@name@use{wtrf@#4@namespace}#3\wtrf@trim@spaces@noexp{#1}}%
  \else
    \wtrf@name@use{wtrf@#4@sep}%
    \wtrf@name@use{wtrf@#4@refcmd}{%
      \wtrf@name@use{wtrf@#4@namespace}#3\wtrf@trim@spaces@noexp{#1}}%
    \wtrf@construct@#2\wtrf@nil{#3}{#4}%
  \fi}

% Defining \setrefstyle command
\NewDocumentCommand{\setrefstyle}{mm}{%
  \@for\wtrf@temp@ref@type:=#1\do{%
    \wtrf@trim@spaces@in\wtrf@temp@ref@type
    \expandafter\wtrf@setrefstyle\expandafter{\wtrf@temp@ref@type}{#2}}}
\def\wtrf@setrefstyle#1#2{%
  \wtrf@if@reftype@not@exists{#1}{%
    \wtrf@error
      {ref type `#1' does not exist}
      {Declare ref type before using it}%
  }{% else
    \setkeys[wtrf]{#1-style}{#2}%
  }}

% All done
\endinput

%% EOF