% Maintained by Matthew Bertucci, 2024-present
% Please report all issues and feature requests at https://github.com/mbertucci47/keytheorems
% This work is licensed under the LPPL version 1.3c or later: https://www.latex-project.org/lppl.txt
\NeedsTeXFormat{LaTeX2e}[2023-06-01]
\ProvidesExplPackage{keytheorems}{2024-09-22}{0.1.4}{l3keys interface to amsthm}

\IfFormatAtLeastTF { 2024-06-01 } { }
  {
    \RequirePackage{nameref} % to avoid ltproperties in code below
    \cs_generate_variant:Nn \cs_set:Npn { Npe }
    \cs_generate_variant:Nn \iow_shipout:Nn { Ne }
    \cs_generate_variant:Nn \keys_set:nn { ne }
    \cs_generate_variant:Nn \msg_warning:nnn { nne }
    \cs_generate_variant:Nn \tl_put_right:Nn { Ne }
    \ProvideDocumentCommand \IfPackageLoadedT { m m }
      { \IfPackageLoadedTF{#1}{#2}{ } }
    \ProvideDocumentCommand \IfPackageLoadedF { m m }
      { \IfPackageLoadedTF{#1}{ }{#2} }
    \ProvideDocumentCommand \IfClassLoadedT { m m }
      { \IfClassLoadedTF{#1}{#2}{ } }
  }
\RequirePackage{aliascnt} % for sibling theorems
\RequirePackage{amsthm}
% ^ ams classes have way of ignoring this so don't need to check if they're loaded
\RequirePackage{refcount} % for \getrefnumber
\RequirePackage{translations} % for translating "List of Theorems"

%%%%%%%%%%%%%%%%%%%%%%
%%% Error Messages %%%
%%%%%%%%%%%%%%%%%%%%%%

\msg_new:nnn { keytheorems } { thmtools-before }
  {
    keytheorems~is~not~compatible~with~thmtools.~
    Try~replacing~\protect\usepackage{thmtools}~with~
    \protect\usepackage[thmtools-compat]{keytheorems}.
  }
\msg_new:nnn { keytheorems } { thmtools-after }
  {
    keytheorems~is~not~compatible~with~thmtools.~
    This~will~not~work~as~you~think!~
    Try~replacing~\protect\usepackage{thmtools}~with~
    \protect\usepackage[thmtools-compat]{keytheorems}.
  }
\msg_new:nnn { keytheorems } { no-stored-theorem }
  {
    No~stored~theorem~'#1'~found!~
    Try~compiling~again.~If~that~doesn't~work,~
    check~the~spelling~of~'#1'.
  }
\msg_new:nnn { keytheorems } { no-prop-for-stored-theorem }
  {
    No~property~'#1'~found~for~stored~theorem~'#2'.
  }
\msg_new:nnn { keytheorems } { store-reversed-not-got }
  {
    'store*=#1'~only~makes~sense~if~you've~called~\protect\getkeytheorem{#1}.~
    Check~that~\protect\getkeytheorem{#1}~is~called~and~compile~again.
  }
\msg_new:nnn { keytheorems } { restate-body-never-got }
  {
    With~'store*=#1',~\protect\getkeytheorem[body]{#1}~only~makes~sense~if~
    \protect\getkeytheorem{#1}~has~been~called.~
    Check~that~\protect\getkeytheorem{#1}~is~called~and~compile~again.
  }
\msg_new:nnn { keytheorems } { store-reversed-called-twice }
  {
    With~'store*=#1',~\protect\getkeytheorem{#1}~can~be~called~only~once.
  }
\msg_new:nnn { keytheorems } { undefined-thm-hook }
  {
    No~theorem~hook~'#1'.~Check~the~spelling.~
    Should~be~one~of~'prehead',~'posthead',~'prefoot',~'postfoot',~or'restated'.
  }
\msg_new:nnn { keytheorems } { hyperref-Autoref }
  {
    You~have~not~loaded~hyperref.~The~\protect\Autoref\space command~needs~
    hyperref~to~work.
  }
\msg_new:nnn { keytheorems } { no-Autorefname }
  {
    No~Autoref~name~for~'#1'.~
    Please~define~\c_backslash_str #1Autorefname.
  }
\msg_new:nnn { keytheorems } { thmstyle-undefined }
  {
    Theorem~style~'#1'~undefined.~
    Use~\protect\newkeytheoremstyle\space instead.
  }
\msg_new:nnn { keytheorems } { thmstyle-defined }
  {
    Theorem~style~'#1'~already~defined.~
    Use~\protect\renewkeytheoremstyle\space instead.
  }
\msg_new:nnn { keytheorems } { title-code-with-AMS }
  {
    The~'title-code'~key~has~no~effect~with~an~AMS~class.
  }

% Error if thmtools loaded since compilation hangs.
% If thmtools loaded after, produce warning.
\IfPackageLoadedTF { thmtools }
  {
    \msg_fatal:nn { keytheorems } { thmtools-before }
  }
  {
    \hook_gput_code:nnn { package/thmtools/before } { . }
      {
        \msg_warning:nn { keytheorems } { thmtools-after }
      }
  }

%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Declare Variables %%%
%%%%%%%%%%%%%%%%%%%%%%%%%

\tl_new:N \l__keythms_tmpa_tl

\bool_new:N \g__keythms_listof_writefile_bool
\bool_gset_false:N \g__keythms_listof_writefile_bool
\bool_new:N \g__keythms_thmtoolscompat_bool
\bool_gset_false:N \g__keythms_thmtoolscompat_bool
\bool_new:N \l__keythms_listofheading_storereversed_bool
\bool_new:N \l__keythms_thm_numbered_bool
\bool_new:N \l__keythms_thm_unlessunique_bool
\bool_new:N \l__keythms_thmuse_listhack_bool
\bool_new:N \l__keythms_thmuse_restating_bool
\clist_new:N \g__keythms_restatecounters_clist
\clist_new:N \l__keythms_thmstyle_savedkeys_clist
\iow_new:N \g__keythms_listof_stream
\prop_new:N \g__keythms_thmnames_prop
\prop_new:N \g__keythms_thmuse_othercounters_prop
\prop_new:N \l__keythms_restate_counters_prop
\tl_new:N \l__keythms_thm_currentthmstyle_tl
\tl_new:N \l__keythms_thm_defaultkeys_tl
\tl_new:N \l__keythms_thm_envname_tl
\tl_new:N \l__keythms_thmstyle_defaultkeys_tl
\tl_new:N \l__keythms_thmstyle_lnotebrace_tl
\tl_new:N \l__keythms_thmstyle_rnotebrace_tl
\tl_new:N \l_keythms_thmuse_envname_tl
\tl_new:N \g__keythms_thmuse_temprestatedata_tl
\tl_new:N \g__keythms_thmuse_temprestatedatareversed_tl

\newcounter{keythms_restate_dummyctr}
\cs_gset:Npn \theHkeythms_restate_dummyctr
  { restate.\arabic{keythms_restate_dummyctr} }
\cs_gset:Npn \thekeythms_restate_dummyctr { }
\newcounter{keythms_continues_dummyctr}
\cs_gset:Npn \theHkeythms_continues_dummyctr
  { continues.\arabic{keythms_continues_dummyctr} }
\cs_gset:Npn \thekeythms_continues_dummyctr { }
\newcounter{keythms_unnumbered_dummyctr}
\cs_gset:Npn \theHkeythms_unnumbered_dummyctr
  { unnumbered.\arabic{keythms_unnumbered_dummyctr} }
\cs_gset:Npn \thekeythms_unnumbered_dummyctr { }

\cs_generate_variant:Nn \hook_gput_code:nnn { nnV }
\cs_generate_variant:Nn \keys_precompile:nnN { nv, nVc }

%%%%%%%%%%%%%%
%%% Styles %%%
%%%%%%%%%%%%%%

% \__keythms_thmstyle_setbraces:nn { <left brace> } { <right brace> }
\cs_new_protected:Npn \__keythms_thmstyle_setbraces:nn #1#2
  {
    \tl_set:Nn \l__keythms_thmstyle_lnotebrace_tl { #1 }
    \tl_set:Nn \l__keythms_thmstyle_rnotebrace_tl { #2 }
  }
\cs_new_protected:Npn \keythms_thmstyle_savethmkey_reqval:n #1
  {
    \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
      { \l_keys_key_str = { #1 } }
  }
\cs_new_protected:Npn \keythms_thmstyle_savethmkey_optval:n #1
  {
    \tl_if_empty:NTF \l_keys_value_tl
      {
        \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
          { \l_keys_key_str }
      }
      {
        \clist_put_right:No \l__keythms_thmstyle_savedkeys_clist
          { \l_keys_key_str = { #1 } }
      }
  }

\keys_define:nn { keytheorems/thmstyle }
  {
    spaceabove    .tl_set:N = \l__keythms_thmstyle_spaceabove_tl,
    spacebelow    .tl_set:N = \l__keythms_thmstyle_spacebelow_tl,
    bodyfont      .tl_set:N = \l__keythms_thmstyle_bodyfont_tl,
    headindent    .tl_set:N = \l__keythms_thmstyle_headindent_tl,
    headfont      .tl_set:N = \l__keythms_thmstyle_headfont_tl,
    headpunct     .tl_set:N = \l__keythms_thmstyle_headpunct_tl,
    postheadspace .tl_set:N = \l__keythms_thmstyle_postheadspace_tl,
    break         .meta:n   = { postheadspace = \newline }, % add error if postheadspace set
    break         .value_forbidden:n = true,
    numberfont    .tl_set:N = \l__keythms_thmstyle_numberfont_tl,
    notefont      .tl_set:N = \l__keythms_thmstyle_notefont_tl,
    notebraces    .code:n   = \exp_after:wN \__keythms_thmstyle_setbraces:nn #1,
    noteseparator .tl_set:N = \l__keythms_thmstyle_noteseparator_tl,
    headstyle     .choice:,
    headstyle / margin .code:n =
      {
        \cs_set:Nn \keythms_thmstyle_headcmd:nnn
          { \makebox[0pt][r]{\NUMBER\ }\NAME\NOTE }
      },
    headstyle / swapnumber .code:n =
      {
        \cs_set:Nn \keythms_thmstyle_headcmd:nnn { \NUMBER\ \NAME\NOTE }
      },
    headstyle / unknown .cs_set:Np = \keythms_thmstyle_headcmd:nnn #1#2#3,
    headformat    .meta:n = { headstyle = #1 },
    inherit-style .choice:,
    inherit-style / plain .meta:n = {},
    inherit-style / definition .meta:n = { bodyfont = \normalfont },
    inherit-style / remark .meta:n =
      {
        headfont = \itshape,
        bodyfont = \normalfont,
        spaceabove = 0.5\topsep,
        spacebelow = 0.5\topsep,
      },
    % thm keys that are saved for later
    numbered              .code:n = \keythms_thmstyle_savethmkey_optval:n { #1 },
    parent                .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    numberwithin          .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    within                .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    sibling               .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    numberlike            .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    sharenumber           .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    preheadhook           .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    postheadhook          .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    prefoothook           .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    postfoothook          .code:n = \keythms_thmstyle_savethmkey_reqval:n { #1 },
    qed                   .code:n = \keythms_thmstyle_savethmkey_optval:n { #1 },
    tcolorbox             .code:n = \keythms_thmstyle_savethmkey_optval:n { #1 },
    tcolorbox-no-titlebar .code:n = \keythms_thmstyle_savethmkey_optval:n { #1 },
  }

\cs_new_protected:Nn \keythms_thmstyle_thmname:n { \thmname{#1} }
\cs_new_protected:Nn \keythms_thmstyle_thmnumber:n { \thmnumber{#1} }
\cs_new_protected:Nn \keythms_thmstyle_thmnote:n { \thmnote{#1} }

%% NOTE: if these are used, user is in charge of spacing with \NAME and \NUMBER
%% QUESTION: should these be moved into def of \newkeytheoremstyle?
\cs_new:Npn \NAME { \keythms_thmstyle_thmname:n { ##1 } }
\cs_new:Npn \NUMBER
  {
    \keythms_thmstyle_thmnumber:n
      {
        \group_begin:
        \exp_not:V \l__keythms_thmstyle_numberfont_tl
        ##2
        \group_end:
      }
  }
\cs_new:Npn \NOTE
  {
    \keythms_thmstyle_thmnote:n
      { \exp_not:V \l__keythms_thmstyle_noteseparator_tl
        \group_begin: % group so notefont doesn't affect headpunct
        \exp_not:V \l__keythms_thmstyle_notefont_tl
        \l__keythms_thmstyle_lnotebrace_tl ##3 \l__keythms_thmstyle_rnotebrace_tl
        \group_end:
      }
  }

\cs_new:Npn \keythms_thmstyle_headcmd_default:nnn #1#2#3
  {
    \keythms_thmstyle_thmname:n { #1 }
    \keythms_thmstyle_thmnumber:n
      { ~
        \group_begin:
        \exp_not:V \l__keythms_thmstyle_numberfont_tl
        #2
        \group_end:
      }
    \keythms_thmstyle_thmnote:n
      { \exp_not:V \l__keythms_thmstyle_noteseparator_tl
        \group_begin: % group so notefont doesn't affect headpunct
        \exp_not:V \l__keythms_thmstyle_notefont_tl
        \l__keythms_thmstyle_lnotebrace_tl #3 \l__keythms_thmstyle_rnotebrace_tl
        \group_end:
      }
  }

\cs_new_protected:Npn \keythms_thmstyle_setdefaultkeys:n #1
  {
    \keys_precompile:nnN { keytheorems/thmstyle }
      { #1 }
      \l__keythms_thmstyle_defaultkeys_tl
  }
\keythms_thmstyle_setdefaultkeys:n
  { % support files may overwrite these defaults
    spaceabove    = \topsep,
    spacebelow    = \topsep,
    bodyfont      = \itshape,
    headindent    = 0pt,
    headfont      = \bfseries,
    headpunct     = {.},
    postheadspace = 5pt plus 1pt minus 1pt,
    numberfont    = \upshape,
    notefont      = \fontseries\mddefault\upshape,
    notebraces    = {(}{)},
    noteseparator = {~},
    headstyle     = \keythms_thmstyle_headcmd_default:nnn{#1}{#2}{#3},
  }

\NewDocumentCommand \newkeytheoremstyle { m m }
  {
    \cs_if_free:cTF { th@ #1 }
      { \keythms_thmstyle_declarestyle:nn { #1 } { #2 } }
      { \msg_error:nnn { keytheorems } { thmstyle-defined } { #1 } }
  }
\NewDocumentCommand \renewkeytheoremstyle { m m }
  {
    \cs_if_free:cTF { th@ #1 }
      { \msg_error:nnn { keytheorems } { thmstyle-undefined } { #1 } }
      { \keythms_thmstyle_declarestyle:nn { #1 } { #2 } }
  }
\NewDocumentCommand \providekeytheoremstyle { m m }
  {
    \cs_if_free:cT { th@ #1 }
      { \keythms_thmstyle_declarestyle:nn { #1 } { #2 } }
  }
\NewDocumentCommand \declarekeytheoremstyle { m m }
  {
    \keythms_thmstyle_declarestyle:nn { #1 } { #2 }
  }

\@onlypreamble \newkeytheoremstyle
\@onlypreamble \renewkeytheoremstyle
\@onlypreamble \providekeytheoremstyle
\@onlypreamble \declarekeytheoremstyle

\cs_new_eq:NN \keythms_thmstyle_new:nnnnnnnnn \newtheoremstyle
\cs_generate_variant:Nn \keythms_thmstyle_new:nnnnnnnnn { nVVVVVVVe }

\cs_new_protected:Npn \keythms_thmstyle_declarestyle:nn #1#2
  {
    \clist_clear:N \l__keythms_thmstyle_savedkeys_clist
    \tl_use:N \l__keythms_thmstyle_defaultkeys_tl
    \keys_set:nn { keytheorems/thmstyle } { #2 }
    \keythms_thmstyle_new:nVVVVVVVe { #1 }
      \l__keythms_thmstyle_spaceabove_tl
      \l__keythms_thmstyle_spacebelow_tl
      \l__keythms_thmstyle_bodyfont_tl
      \l__keythms_thmstyle_headindent_tl
      \l__keythms_thmstyle_headfont_tl
      \l__keythms_thmstyle_headpunct_tl
      \l__keythms_thmstyle_postheadspace_tl
      { \text_expand:n { \keythms_thmstyle_headcmd:nnn{##1}{##2}{##3} } }
    % Define new inherit-style key
    \keys_define:nn { keytheorems/thmstyle }
      { inherit-style / #1 .meta:n = { #2 } }
    \tl_if_exist:cF { l__keythms_thmstyle_ #1 _savedkeys_tl }
      { \tl_new:c { l__keythms_thmstyle_ #1 _savedkeys_tl } }
    \keys_precompile:nVc { keytheorems/thm }
      \l__keythms_thmstyle_savedkeys_clist
      { l__keythms_thmstyle_ #1 _savedkeys_tl }
  }

%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Defining Theorems %%%
%%%%%%%%%%%%%%%%%%%%%%%%%

% FIX: reimplement these without \NewDocumentCommand and \SplitArgument

% \keythms_thm_setrefnames:n { <envname> } { <refname> or <sing,plural> }
\NewDocumentCommand \keythms_thm_setrefnames:nn
  { m >{\SplitArgument{1}{,}} m }
  { \__keythms_thm_setrefnames_aux:nnn{#1}#2 }
\cs_new_protected:Npn \__keythms_thm_setrefnames_aux:nnn #1#2#3
  {
    \cs_set:cpn { #1 autorefname } { #2 }
    \IfPackageLoadedT { cleveref }
      { 
        \tl_if_novalue:nTF { #3 }
          { \crefname{#1}{#2}{\textbf{??~(pl.~#2)}} }
          { \crefname{#1}{#2}{#3} }
      }
  }
\cs_generate_variant:Nn \keythms_thm_setrefnames:nn { nV }

% \keythms_thm_setRefnames:n { <envname> } { <refname> or <sing,plural> }
\NewDocumentCommand \keythms_thm_setRefnames:nn
  { m >{\SplitArgument{1}{,}} m }
  { \__keythms_thm_setRefnames_aux:nnn{#1}#2 }
\cs_new_protected:Npn \__keythms_thm_setRefnames_aux:nnn #1#2#3
  {
    \cs_set:cpn { #1 Autorefname } { #2 }
    \IfPackageLoadedT { cleveref }
      { 
        \tl_if_novalue:nTF { #3 }
          { \Crefname{#1}{#2}{\textbf{??~(pl.~#2)}} }
          { \Crefname{#1}{#2}{#3} }
      }
  }
\cs_generate_variant:Nn \keythms_thm_setRefnames:nn { nV }

\keys_define:nn { keytheorems/thm }
  {
    name           .tl_set:N  = \l__keythms_thm_name_tl,
    title          .meta:n    = { name = #1 },
    heading        .meta:n    = { name = #1 },
    refname        .tl_set:N  = \l__keythms_thm_refname_tl,
    Refname        .tl_set:N  = \l__keythms_thm_Refname_tl,
    numbered       .choice:,
    numbered / true .code:n   = \bool_set_true:N \l__keythms_thm_numbered_bool,
    numbered / false .code:n  = \bool_set_false:N \l__keythms_thm_numbered_bool,
    numbered / yes .meta:n    = { numbered = true },
    numbered / no  .meta:n    = { numbered = false },
    numbered / unless-unique .code:n = 
      {
        \bool_set_true:N \l__keythms_thm_unlessunique_bool
      },
    numbered / unless~unique .meta:n = { numbered = unless-unique },
    numbered       .default:n = true,
    parent         .tl_set:N  = \l__keythms_thm_parent_tl,
    numberwithin   .meta:n    = { parent = #1 },
    within         .meta:n    = { parent = #1 },
    sibling        .tl_set:N  = \l__keythms_thm_sibling_tl,
    numberlike     .meta:n    = { sibling = #1 },
    sharenumber    .meta:n    = { sibling = #1 },
    style          .tl_set:N  = \l__keythms_thm_style_tl,
    style          .groups:n  = { style-comes-first },
    preheadhook    .tl_set:N  = \l__keythms_thm_preheadhook_tl,
    postheadhook   .tl_set:N  = \l__keythms_thm_postheadhook_tl,
    prefoothook    .tl_set:N  = \l__keythms_thm_prefoothook_tl,
    postfoothook   .tl_set:N  = \l__keythms_thm_postfoothook_tl,
    qed            .tl_set:N  = \l__keythms_thm_qed_tl,
    qed            .default:n = \c_novalue_tl,
    % ^ distinguish between 'qed' and 'qed={}'
    tcolorbox      .tl_set:N  = \l__keythms_thm_tcbkeys_tl,
    tcolorbox      .default:n = {},
    tcolorbox-no-titlebar .meta:n =
      {
        tcolorbox={
          notitle,
          before~upper={
            \group_begin:
            \__keythms_thm_tcboxtemphead:
            \group_end:
            },
          #1
          }
      },
    tcolorbox-no-titlebar .default:n = {},
  }

% what below is unnecessary? I really don't understand this code.
\cs_new_protected:Npn \__keythms_thm_storedeferredthmhead:n #1
  {
    \if@inlabel \indent \par \fi % eject a section head if one is pending
    \if@nobreak
      \adjust@parskip@nobreak
    \else
    \addpenalty\@beginparpenalty
    \addvspace\@topsep
    \addvspace{-\parskip}
    \fi
    % \global\@inlabeltrue % MY COMMENT: if this is uncommented then spacing after sections is wrong
    \everypar\dth@everypar
    \cs_set:Npn \__keythms_thm_tcboxtemphead: { \normalfont #1 }
    \ignorespaces
  }

\keys_precompile:nnN { keytheorems/thm }
  {
    name         = \q_no_value,
    refname      = \q_no_value,
    Refname      = \q_no_value,
    numbered     = true,
    parent       = {},
    sibling      = {},
    style        = {},
    preheadhook  = {},
    postheadhook = {},
    prefoothook  = {},
    postfoothook = {},
    qed          = \q_no_value,
    tcolorbox    = \q_no_value,
  }
  \l__keythms_thm_defaultkeys_tl

\cs_new_protected:Npn \__keythms_thm_makethmhooks:n #1
  {
    \hook_new:n { keytheorems/#1/prehead }
    \hook_new:n { keytheorems/#1/posthead }
    \hook_new_reversed:n { keytheorems/#1/prefoot }
    \hook_new_reversed:n { keytheorems/#1/postfoot }
    \hook_new:n { keytheorems/#1/restated }
  }

% Make generic theorem hooks
\__keythms_thm_makethmhooks:n { allthms }

% \newkeytheorem{<name>}{<keys>}
\NewDocumentCommand \newkeytheorem { m O{} }
  {
    \clist_map_inline:nn { #1 } % define multiple theorems at once
      { \keythms_thm_newkeythm:nn { ##1 } { #2 } }
  }

\@onlypreamble \newkeytheorem

% to prevent error when plain, remark, or definition style used
\tl_new:N \l__keythms_thmstyle_plain_savedkeys_tl
\tl_new:N \l__keythms_thmstyle_remark_savedkeys_tl
\tl_new:N \l__keythms_thmstyle_definition_savedkeys_tl

% \keythms_thm_newkeythm:nn { <envname> } { <keys> }
\cs_new_protected:Npn \keythms_thm_newkeythm:nn #1#2
  {
    % Store envname
    \tl_set:Nn \l__keythms_thm_envname_tl { #1 }
    % Make unless-unique false by default (can't precompile this)
    \bool_set_false:N \l__keythms_thm_unlessunique_bool
    % Set default keys
    \tl_use:N \l__keythms_thm_defaultkeys_tl
    % First set style so we can pick up additional thm keys, then overwrite if necessary
    \keys_set_groups:nnn { keytheorems/thm } { style-comes-first } { #2 }
    % Store theorem style
    \tl_set:Ne \l__keythms_thm_currentthmstyle_tl { \the\thm@style }
    \tl_if_empty:NTF \l__keythms_thm_style_tl
      { % if \theoremstyle set, also use saved thm keys
        \tl_if_exist:cT {l__keythms_thmstyle_ \l__keythms_thm_currentthmstyle_tl _savedkeys_tl}
          { \tl_use:c {l__keythms_thmstyle_ \l__keythms_thm_currentthmstyle_tl _savedkeys_tl} }
      }
      {
        % Temporarily set theorem style
        \__keythms_theoremstyle:n { \l__keythms_thm_style_tl }
        % If thm keys given in style, call now (possibly overwritten in next step)
        % but don't error if user uses a style defined with just \newtheoremstyle
        \tl_if_exist:cT { l__keythms_thmstyle_ \l__keythms_thm_style_tl _savedkeys_tl }
          { \tl_use:c { l__keythms_thmstyle_ \l__keythms_thm_style_tl _savedkeys_tl } }
      }
    % Set env-specific keys
    \keys_set:nn { keytheorems/thm } { #2 }
    % Set up env-specific hooks
    \__keythms_thm_makethmhooks:n { #1 }
    % Add to env-specific hooks (use label so code given in keys is outermost)
    % NOTE: faster to check if empty than add empty code to hook
    \tl_if_empty:NF \l__keythms_thm_preheadhook_tl
      {
        \hook_gput_code:nnV { keytheorems/#1/prehead }
          { keythms_hook_keys } \l__keythms_thm_preheadhook_tl
      }
    \tl_if_empty:NF \l__keythms_thm_postheadhook_tl
      {
        \hook_gput_code:nnV { keytheorems/#1/posthead }
          { keythms_hook_keys } \l__keythms_thm_postheadhook_tl
      }
    \tl_if_empty:NF \l__keythms_thm_prefoothook_tl
      {
        \hook_gput_code:nnV { keytheorems/#1/prefoot }
          { keythms_hook_keys } \l__keythms_thm_prefoothook_tl
      }
    \tl_if_empty:NF \l__keythms_thm_postfoothook_tl
      {
        \hook_gput_code:nnV { keytheorems/#1/postfoot }
          { keythms_hook_keys } \l__keythms_thm_postfoothook_tl
      }
    % Set name if none given
    \quark_if_no_value:NT \l__keythms_thm_name_tl % use quark so name={} is valid
      {
        % use e so \text_titlecase called only once per theorem definition,
        %  not each time the theorem is used
        \tl_set:Ne \l__keythms_thm_name_tl 
          { \text_titlecase_first:n { #1 } }
      }
    % associate formatted name with envname in prop list
    \prop_gput:NnV \g__keythms_thmnames_prop { #1 } \l__keythms_thm_name_tl
    % Call correct \newtheorem variant
    \bool_if:NTF \l__keythms_thm_unlessunique_bool
      {
        % [unq] is required since aux is read at begindocument
        % (technically right before) which is after theorem is defined
        \RequirePackage[unq]{unique}
        \tl_if_empty:NTF \l__keythms_thm_parent_tl
          {
            \hook_gput_code:nnn { keytheorems/#1/prehead }
              { keythms_hook_keys } { \setuniqmark { #1 } }
            \ifuniq{ #1 }
              { \bool_set_false:N \l__keythms_thm_numbered_bool }
              { \bool_set_true:N \l__keythms_thm_numbered_bool }
            \bool_if:NTF \l__keythms_thm_numbered_bool
              {
                \tl_if_empty:NTF \l__keythms_thm_sibling_tl
                  {
                    \__keythms_thm_new_numbered:nV { #1 } \l__keythms_thm_name_tl
                  }
                  {
                    \exp_args:NnV \newaliascnt { #1 } \l__keythms_thm_sibling_tl
                    \__keythms_thm_new_sibling:nVn { #1 }
                      \l__keythms_thm_name_tl { #1 }
                    \aliascntresetthe { #1 }
                  }
              }
              {
                \__keythms_thm_new_unnumbered:nV { #1 } \l__keythms_thm_name_tl
                \hook_gput_code:nnn { keytheorems/#1/prehead } { keythms_hook_keys }
                  {
                    \keythms_if_restating:F
                      { \refstepcounter{ keythms_unnumbered_dummyctr } }
                  }
              }
          }
          {
            \__keythms_thm_new_uuwithparent:nVV { #1 }
              \l__keythms_thm_name_tl \l__keythms_thm_parent_tl
          }
      }
      {
        \bool_if:NTF \l__keythms_thm_numbered_bool
          {
            \tl_if_empty:NTF \l__keythms_thm_parent_tl
              {
                \tl_if_empty:NTF \l__keythms_thm_sibling_tl
                  {
                    \__keythms_thm_new_numbered:nV { #1 } \l__keythms_thm_name_tl
                  }
                  {
                    \exp_args:NnV \newaliascnt { #1 } \l__keythms_thm_sibling_tl
                    \__keythms_thm_new_sibling:nVn { #1 }
                      \l__keythms_thm_name_tl { #1 }
                    \aliascntresetthe { #1 }
                  }
              }
              {
                \__keythms_thm_new_parent:nVV { #1 }
                  \l__keythms_thm_name_tl \l__keythms_thm_parent_tl
              }
          }
          {
            \__keythms_thm_new_unnumbered:nV { #1 } \l__keythms_thm_name_tl
            \hook_gput_code:nnn { keytheorems/#1/prehead } { keythms_hook_keys }
              {
                \keythms_if_restating:F
                  { \refstepcounter{ keythms_unnumbered_dummyctr } }
              }
          }
      }
    % Store theorem def and redefine it with keys
    \keythms_keyify_theorem:n { #1 }
    % define \<env>autorefname and \<env>Autorefname, might be redefined next
    \exp_args:NnV \cs_set:cpn { #1 autorefname } \l__keythms_thm_name_tl
    \exp_args:NnV \cs_set:cpn { #1 Autorefname } \l__keythms_thm_name_tl
    % Set ref names
    \quark_if_no_value:NF \l__keythms_thm_refname_tl
      { \keythms_thm_setrefnames:nV { #1 } \l__keythms_thm_refname_tl }
    \quark_if_no_value:NF \l__keythms_thm_Refname_tl 
      { \keythms_thm_setRefnames:nV { #1 } \l__keythms_thm_Refname_tl }
    % Set up qed if needed
    \quark_if_no_value:NF \l__keythms_thm_qed_tl
      {
        \exp_args:Nno \__keythms_thm_qedcode:nn { #1 } { \l__keythms_thm_qed_tl }
      }
    % Set up tcolorbox if needed
    \quark_if_no_value:NF \l__keythms_thm_tcbkeys_tl
      {
        \exp_args:Nno \__keythms_thm_tcboxcode:nn { #1 }
          { \l__keythms_thm_tcbkeys_tl }
      }
    % Set up list-of definition
    \cs_set_eq:cN { l@ #1 } \keythms_listof_tocline:
    % Set default list-of display command
    \__keythms_listof_show_aux:n { #1 }
    % Set theorem style back to original state if needed
    \tl_if_empty:NF \l__keythms_thm_style_tl
      {
        \__keythms_theoremstyle:V \l__keythms_thm_currentthmstyle_tl
      }
  }

\cs_new_protected:Npn \__keythms_thm_tcboxcode:nn #1#2
  {
    \RequirePackage{tcolorbox}
    \hook_gput_code:nnn { keytheorems/#1/prehead }
      { keythms_tcbox }
      {
        \cs_set_eq:NN \deferred@thm@head \__keythms_thm_storedeferredthmhead:n
        \cs_set_eq:NN \Hy@theorem@makelinktarget \use_none:n
        % ^ don't like playing with hyperref internals... but don't see around
        %   it because hyperref tries to add to para hook which doesn't work
        %   when title set up the way we do it
        \cs_set_protected:Npn \thm@space@setup { \thm@preskip=0pt \thm@postskip=0pt }
        % ^ to match tcolorbox defaults; shouldn't interfere with user styles
      }
    \hook_gset_rule:nnnn { keytheorems/#1/posthead }
      { keythms_tcbox } { before } { keythms_hook_keys }
    \hook_gset_rule:nnnn { keytheorems/#1/prefoot }
      { keythms_tcbox } { after } { keythms_hook_keys }
    \hook_gset_rule:nnnn { keytheorems/#1/prefoot }
      { keythms_tcbox } { after } { keythms_qed }
    \tcbset
      {
        keythms_tcbox_#1/.style =
          {
            savedelimiter=#1,
            title={ \__keythms_thm_tcboxtemphead: },
          }
      }
    \bool_if:NT \l__keythms_thm_numbered_bool
      {
        \hook_gput_code:nnn { begindocument } { . }
          {
            \IfPackageLoadedF{cleveref}
              { % hyperref doesn't patch \@thm if cleveref loaded
                \tcbset
                  {
                    keythms_tcbox_#1/.append~style = % fix hyperlinking
                      { phantom={ \MakeLinkTarget*{\@currentHref} } }
                  }
              }
          }
      }
    \hook_gput_code:nnn { keytheorems/#1/posthead } { keythms_tcbox }
      { \begin{tcolorbox}[keythms_tcbox_#1,#2] }
    \hook_gput_code:nnn { keytheorems/#1/prefoot } { keythms_tcbox }
      { \end{tcolorbox} }
  }
\cs_new_protected:Npn \__keythms_thm_qedcode:nn #1#2
  {
    \hook_gput_code:nnn { keytheorems/#1/posthead }
      { keythms_qed }
      {
        \exp_args:No \tl_if_novalue:nF { #2 } { \protected@edef\qedsymbol{#2} }
        \pushQED{\qed}
      }
    \hook_gput_code:nnn { keytheorems/#1/prefoot }
      { keythms_qed }
      {
        \exp_args:No \tl_if_novalue:nF { #2 } { \protected@edef\qedsymbol{#2} }
        \popQED
      }
  }

\cs_new_eq:NN \__keythms_theoremstyle:n \theoremstyle
\cs_generate_variant:Nn \__keythms_theoremstyle:n { V }

% \newtheorem variants
\cs_new_eq:NN \__keythms_thm_new:w \newtheorem

\cs_new_protected:Npn \__keythms_thm_new_numbered:nn #1#2
  { \__keythms_thm_new:w { #1 } { #2 } }
\cs_generate_variant:Nn \__keythms_thm_new_numbered:nn { nV }

\cs_new_protected:Npn \__keythms_thm_new_unnumbered:nn #1#2
  { \__keythms_thm_new:w* { #1 } { #2 } }
\cs_generate_variant:Nn \__keythms_thm_new_unnumbered:nn { nV }

\cs_new_protected:Npn \__keythms_thm_new_parent:nnn #1#2#3
  { \__keythms_thm_new:w { #1 } { #2 } [ #3 ] }
\cs_generate_variant:Nn \__keythms_thm_new_parent:nnn { nVV }

\cs_new_protected:Npn \__keythms_thm_new_sibling:nnn #1#2#3
  { \__keythms_thm_new:w { #1 } [ #3 ] { #2 } }
\cs_generate_variant:Nn \__keythms_thm_new_sibling:nnn { nV }

\cs_new_protected:Npn \__keythms_thm_new_uuwithparent:nnn #1#2#3
  {
    \cs_undefine:c { keythms_orig_nonumber_#1 } % for renew, declare
    \__keythms_thm_new_unnumbered:nn { keythms_orig_nonumber_#1 } { #2 }
    \__keythms_thm_new_parent:nnn { #1 } { #2 } { #3 }
    \DeclareEnvironmentCopy { keythms_orig_withparent_#1 } { #1 }
    \renewenvironment { #1 } % opt arg is implicit
      {
        \setuniqmark{ #1. \use:c {the #3} }
        \ifuniq{ #1. \use:c {the #3} }
          {
            \keythms_if_restating:F
              { \refstepcounter{ keythms_unnumbered_dummyctr } }
            \begin{keythms_orig_nonumber_#1}
          }
          {
            \begin{keythms_orig_withparent_#1}
          }
      }
      {
        \ifuniq{ #1. \use:c {the #3} }
          { \end{keythms_orig_nonumber_#1} }
          { \end{keythms_orig_withparent_#1} }
      }
  }
\cs_generate_variant:Nn \__keythms_thm_new_uuwithparent:nnn { nVV }

% for getting notes with continues*, use nameref if available, otherwise ltproperties
\hook_gput_code:nnn { begindocument } { . }
  {
    \IfPackageLoadedTF { nameref }
      {
        \cs_new:Npn \__keythms_thmuse_recordnote: { } % nameref takes care of this
        \cs_new:Npn \__keythms_getrecordednote:n #1
          {
            \getrefbykeydefault{ #1 }{ name }{ }
          }
      }
      {
        \property_new:nnnn { keytheorems/recordednote } { now } { }
          { \l__keythms_thmuse_note_tl }
        \cs_new:Npn \__keythms_getrecordednote:n #1
          {
            \property_ref:nn { keythms_recordednote_#1 }
              { keytheorems/recordednote }
          }
        \cs_new:Npn \__keythms_thmuse_recordnote:
          {
            \tl_if_empty:NF \l__keythms_thmuse_note_tl
              {
                \RecordProperties
                  { keythms_recordednote_\l__keythms_thmuse_label_tl }
                  { keytheorems/recordednote }
              }
          }
      }
  }

\keys_define:nn { keytheorems/thmuse }
  {
    label      .tl_set:N = \l__keythms_thmuse_label_tl,
    note       .tl_set:N = \l__keythms_thmuse_note_tl,
    note       .initial:n = {},
    name       .meta:n   = { note = #1 },
    % ^ for compatibility. "name" is ambiguous and doesn't match amsthm language
    short-note .code:n   = {}, % these do nothing at point of use
    short-name .code:n   = {},
    continues  .tl_set:N = \l__keythms_thmuse_contlabel_tl,
    continues* .code:n   =
      {
        \keys_set:nn { keytheorems/thmuse } { continues = #1 }
        \protected@edef \l__keythms_tmpa_tl { \__keythms_getrecordednote:n{#1} }
        \tl_if_empty:NF \l__keythms_tmpa_tl
          {
            \keys_set:nn { keytheorems/thmuse }
              { note = \l__keythms_tmpa_tl }
          }
      },
    store      .tl_set:N = \l__keythms_thmuse_store_tl, % should this be .tl_set_e:N ?
    %store      .default:n = \q_no_value, % ={name} causes issues
    restate    .meta:n   = { store = #1 }, % thmtools compatibility
    store*     .tl_set:N = \l__keythms_thmuse_storereversed_tl,
    restate*   .meta:n   = { store* = #1 },
    restate-keys .clist_set:N = \l__keythms_thmuse_restatekeys_clist,
    listhack   .choice:, % need equals sign
    listhack / true .code:n = \bool_set_true:N \l__keythms_thmuse_listhack_bool,
    listhack / false .code:n = \bool_set_false:N \l__keythms_thmuse_listhack_bool,
    listhack   .initial:n = false,
    seq        .code:n = {},
  }

\cs_new_protected:Npn \keythms_keyify_theorem:n #1
  { % #1 = theorem name
    \DeclareEnvironmentCopy { keythms_orig_#1 } { #1 }
    \DeclareDocumentEnvironment { keythms_grab_#1 } { m m +b }
      { % ##1 = keys, ##2 = note, ##3 = theorem body
        \__keythms_thm_prehead_code:n { #1 }
        \begin{keythms_orig_#1}[{##2}]
        \clist_map_inline:Nn \g__keythms_restatecounters_clist
          {
            \prop_gput:Nne \g__keythms_thmuse_othercounters_prop { ####1 }
              { \the\value{####1} }
          }
        \__keythms_thm_posthead_code:n { #1 }
        % below needs to come after posthead so that correct \@currentHref
        % is stored for tcolorbox theorems
        \__keythms_thm_addcontentsdata:nnnn { #1 }
          { \prop_to_keyval:N \g__keythms_thmuse_othercounters_prop }
          { ##1 } { ##3 }
        \__keythms_thm_tempstorerestatedata:nnn { #1 } { ##1 } { ##3 }
        ##3
        \__keythms_thm_prefoot_code:n { #1 }
        \end{keythms_orig_#1}
        \__keythms_thm_postfoot_code:n { #1 }
      }
      {}
    \DeclareDocumentEnvironment { keythms_grabreversed_#1 } { m m +b }
      { % ##1 = keys, ##2 = note, ##3 = theorem body
        \tl_if_exist:cTF
          { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _restatecounters_tl }
          {
            \bool_set_true:N \l__keythms_thmuse_restating_bool
            \exp_args:NNe \prop_set_from_keyval:Nn \l__keythms_restate_counters_prop
              { \tl_use:c { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _restatecounters_tl } }
            \prop_map_inline:Nn \l__keythms_restate_counters_prop
              {
                \tl_set:ce { l_keythms_restate_current_####1_tl }
                  { \the\value{####1} }
                \setcounter { ####1 } { ####2 }
                % ^ FIX: what if eq's numbered by section, theorem, etc.? The
                %        thmtools code is opaque.... Or maybe should be up to the
                %        user to say "restate-counters={section,chapter,...}".
                \cs_set:cpn { theH ####1 }
                  { \use:c { the ####1 } . \theHkeythms_restate_dummyctr }
              }
            \tl_if_empty:cTF
              { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _label_tl }
              { \refstepcounter{keythms_restate_dummyctr} } % for unnumbered theorems
              {
                \cs_set:cpn { the #1 }
                  { \tl_use:c { c__keythms_storeatbegin_ \l__keythms_thmuse_storereversed_tl _label_tl } }
                \cs_set_eq:cN { c@ #1 } \c@keythms_restate_dummyctr
                \cs_set_eq:cN { theH #1 } \theHkeythms_restate_dummyctr
                % ^ why are the last two lines here? We shouldn't be referencing
                %   restated theorems. Think it's a remnant of thmtools
                % WRONG: needed to make numbering correct after restated theorem.
                % not sure about theH. <- this is needed to prevent duplicate anchors
              }
           }
           {
             \msg_warning:nne { keytheorems } { store-reversed-not-got }
               { \l__keythms_thmuse_storereversed_tl }
           }
        \renewcommand\label[2][]{} % disable \label (opt arg in case cleveref loaded)
        \cs_set_eq:NN \ltx@label \use_none:n % disable \ltx@label
        \cs_set_eq:NN \property_record:nn \use_none:nn % disable \RecordProperties
        \cs_set_eq:NN \setuniqmark \use_none:n % work with numbered=unless-unique
        % QUESTION: also disable \hyper@@anchor? \MakeLinkTarget?
        \hook_use:n { keytheorems/#1/restated }
        \hook_use:n { keytheorems/allthms/restated }
        \__keythms_thm_prehead_code:n { #1 }
        \begin{keythms_orig_#1}[{##2}]
        \__keythms_thm_posthead_code:n { #1 }
        % below needs to come after posthead so that correct \@currentHref
        % is stored for tcolorbox theorems
        \__keythms_thm_addstoredreverseddata:nnn { #1 } { ##1 } { ##3 }
        \__keythms_thm_tempstorerestatedatareversed:nnn { #1 } { ##1 } { ##3 }
        ##3
        \__keythms_thm_prefoot_code:n { #1 }
        \end{keythms_orig_#1}
        \__keythms_thm_postfoot_code:n { #1 }
        \prop_map_inline:Nn \l__keythms_restate_counters_prop
          {
            \exp_args:Nnc \setcounter { ####1 }
              { l_keythms_restate_current_####1_tl }
          }
      }
      { }
      % NOTE: have to do a lot of shenanigans to make sure the begin/end of grabbed
      %       theorem env captures only the body and no package code.
      %       This is the price of on-the-fly redefining the env to grab body
      \RenewDocumentEnvironment { #1 } { ={note} O{} }
        {
          \keys_set:nn { keytheorems/thmuse } { ##1 }
          \tl_if_empty:NF \l__keythms_thmuse_store_tl
            {
              \bool_gset_true:N \g__keythms_listof_writefile_bool
              \cs_set_eq:NN \__keythms_withhooks_begin:nnn \__keythms_grab_begin:nnn
              \cs_set_eq:NN \__keythms_withhooks_begin:nnV \__keythms_grab_begin:nnV
              \cs_set_eq:NN \__keythms_withhooks_end:n \__keythms_grab_end:n
            }
          \tl_if_empty:NF \l__keythms_thmuse_storereversed_tl
            {
              \bool_gset_true:N \g__keythms_listof_writefile_bool
              \cs_set_eq:NN \__keythms_withhooks_begin:nnn \__keythms_grabreversed_begin:nnn
              \cs_set_eq:NN \__keythms_withhooks_begin:nnV \__keythms_grabreversed_begin:nnV
              \cs_set_eq:NN \__keythms_withhooks_end:n \__keythms_grabreversed_end:n
            }
          \__keythms_thm_prehead_continues_code:n { #1 }
          \__keythms_withhooks_begin:nnV { #1 } { ##1 } \l__keythms_thmuse_note_tl
        }
        {
          \__keythms_withhooks_end:n { #1 }
          \tl_if_empty:NF \l__keythms_thmuse_store_tl
            {
              \cs_if_exist:cF
                { __keythms_getthm_ \l__keythms_thmuse_store_tl _theorem }
                {
                  \cs_new:cpe
                    { __keythms_getthm_ \l__keythms_thmuse_store_tl _theorem }
                    {
                      \exp_not:N \__keythms_getthm_theorem:nnnnn
                      \exp_not:o { \g__keythms_thmuse_temprestatedata_tl }
                    }
                  \cs_new:cpe
                    { __keythms_getthm_ \l__keythms_thmuse_store_tl _body }
                    {
                      \exp_not:N \__keythms_getthm_body:nn
                      \exp_args:No \exp_not:o
                        {
                          \exp_after:wN \__keythms_use_iii_v_braced:nnnnn
                            \g__keythms_thmuse_temprestatedata_tl
                        }
                    }
                }
            }
          \tl_if_empty:NF \l__keythms_thmuse_storereversed_tl
            {
              \cs_if_exist:cF
                { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _theorem }
                {
                  \cs_new:cpe
                    { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _theorem }
                    {
                      \exp_not:N \__keythms_getthmreversed_theorem:nnn
                      \exp_not:o { \g__keythms_thmuse_temprestatedatareversed_tl }
                    }
                  \cs_new:cpn
                    { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _body }
                    {
                      \textbf{??}
                      \msg_warning:nnn { keytheorems } { restate-body-never-got }
                        { #1 }
                    }
                }
      }
        }
  }
\cs_new:Npn \__keythms_use_iii_v_braced:nnnnn #1#2#3#4#5 { {#3}{#5} }

\cs_new_protected:Npn \__keythms_withhooks_begin:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = note
    \__keythms_thm_prehead_code:n { #1 }
    \begin{keythms_orig_#1}[{#3}]
    \__keythms_thm_posthead_code:n { #1 }
    \__keythms_thm_addcontentsdata:nnnn { #1 } { } { #2 } { }
    \ignorespaces % I hope this is alright
  }
\cs_generate_variant:Nn \__keythms_withhooks_begin:nnn { nnV }
\cs_new_protected:Npn \__keythms_withhooks_end:n #1
  {
    \__keythms_thm_prefoot_code:n { #1 }
    \end{keythms_orig_#1}
    \__keythms_thm_postfoot_code:n { #1 }
  }
\cs_new_protected:Npn \__keythms_grab_begin:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = note
    \begin{keythms_grab_#1}{#2}{#3}
  }
\cs_generate_variant:Nn \__keythms_grab_begin:nnn { nnV }
\cs_new_protected:Npn \__keythms_grab_end:n #1 { \end{keythms_grab_#1} }

\cs_new_protected:Npn \__keythms_grabreversed_begin:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = note
    \begin{keythms_grabreversed_#1}{#2}{#3}
  }
\cs_generate_variant:Nn \__keythms_grabreversed_begin:nnn { nnV }
\cs_new_protected:Npn \__keythms_grabreversed_end:n #1
  { \end{keythms_grabreversed_#1} }

\cs_new_protected:Npn \__keythms_orig_begin:nn #1#2
  { \begin{keythms_orig_#1}[{#2}] }
\cs_generate_variant:Nn \__keythms_orig_begin:nn { nV }
\cs_new_protected:Npn \__keythms_orig_end:n #1 { \end{keythms_orig_#1} }

\cs_new_protected:Npn \__keythms_thm_prehead_code:n #1
  { % #1 = theorem name
    \tl_set:Nn \l_keythms_thmuse_envname_tl { #1 }
    \hook_use:n { keytheorems/#1/prehead }
    \hook_use:n { keytheorems/allthms/prehead }
  }
%% this below has to be separate from prehead_code above since we need to add
%% continues-code to note before retrieving it in \__keythms_withhooks_begin:nnV
\cs_new_protected:Npn \__keythms_thm_prehead_continues_code:n #1
  { % #1 = theorem name
    \tl_if_empty:NF \l__keythms_thmuse_contlabel_tl
      {
        \tl_if_empty:NF \l__keythms_thmuse_note_tl
          { \tl_put_right:Nn \l__keythms_thmuse_note_tl { , ~ } }
        \tl_put_right:Ne \l__keythms_thmuse_note_tl
          { \__keythms_thmuse_continues:V \l__keythms_thmuse_contlabel_tl }
        \cs_set:cpn { the #1 }
          {
            \getrefnumber { \l__keythms_thmuse_contlabel_tl }
          }
        \cs_set_eq:cN { c@ #1 } \c@keythms_continues_dummyctr
        \cs_set_eq:cN { theH #1 } \theHkeythms_continues_dummyctr
        %\cs_set_eq:NN \setuniqmark \use_none:n % not the right fix
      }
  }
\cs_new_protected:Npn \__keythms_thm_posthead_code:n #1
  { % #1 = theorem name
    \hook_use:n { keytheorems/#1/posthead }
    \hook_use:n { keytheorems/allthms/posthead }
    \tl_if_empty:NF \l__keythms_thmuse_label_tl
      {
        \label{ \l__keythms_thmuse_label_tl }
        \__keythms_thmuse_recordnote:
      }
    \bool_if:NT \l__keythms_thmuse_listhack_bool
      { % straight from thm-amsthm.sty
        \leavevmode
        \vspace{-\baselineskip}%
        \par
        \everypar{\setbox\z@\lastbox\everypar{}}%
      }
  }
\cs_new_protected:Npn \__keythms_thm_prefoot_code:n #1
  { % #1 = theorem name
    \hook_use:n { keytheorems/allthms/prefoot }
    \hook_use:n { keytheorems/#1/prefoot }
  }
\cs_new_protected:Npn \__keythms_thm_postfoot_code:n #1
  { % #1 = theorem name
    \hook_use:n { keytheorems/allthms/postfoot }
    \hook_use:n { keytheorems/#1/postfoot }
  }
\cs_new_protected:Npn \__keythms_thm_addcontentsdata:nnnn #1#2#3#4
  { % #1 = theorem name, #2 = stored counters, #3 = keys, #4 = body
    \keythms_listof_chaptervspacehack:
    \iow_shipout:Ne \@auxout
      {
        \exp_not:N \@writefile { thlist }
          {
            \KeyThmsSavedTheorem{ #1 }
              { \@currentlabel }
              { \@currentHref }
              { \thepage }
              { #2 }
              { \exp_not:n { #3 } } % do we want any expansion here, perhaps
              { \exp_not:n { #4 } } % with \text_expand:n ?
          }
      }
  }
\cs_new_protected:Npn \__keythms_thm_addstoredreverseddata:nnn #1#2#3
  {
    \iow_shipout:Ne \@auxout
      {
        \exp_not:N \@writefile { thlist }
          {
            \KeyThmsSavedTheoremReversed { \l__keythms_thmuse_storereversed_tl }
              { #1 }
              { \exp_not:n { #2 } }
              { \exp_not:n { #3 } }
          }
      }
  }
\cs_new_protected:Npn \__keythms_thm_tempstorerestatedata:nnn #1#2#3
  { % #1 = theorem name, #2 = keys, #3 = body
    \tl_gset:Ne \g__keythms_thmuse_temprestatedata_tl % needs to be global to get out of env
      {
        { #1 }
        { \@currentlabel }
        { \prop_to_keyval:N \g__keythms_thmuse_othercounters_prop }
        { \exp_not:n { #2 } } % do we want any expansion here, perhaps
        { \exp_not:n { #3 } } % with \text_expand:n ?
      }
  }
\cs_new_protected:Npn \__keythms_thm_tempstorerestatedatareversed:nnn #1#2#3
  {
    \tl_gset:Ne \g__keythms_thmuse_temprestatedatareversed_tl % needs to be global to get out of env
      {
        { #1 }
        { \exp_not:n { #2 } }
        { \exp_not:n { #3 } }
      }
  }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Retrieving Theorem Data %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\cs_new_protected:Npn \KeyThmsSavedTheorem #1#2#3#4#5#6#7 % 7th arg is body
  { \use:c { __keythms_thmitem_#1:nnnnnn } {#2}{#3}{#4}{#5}{#6}{#7} }
\cs_new_protected:Npn \KeyThmsSavedTheoremReversed #1#2#3#4 { } % gobble by default

\keys_define:nn { keytheorems/storeatbegin }
  {
    store    .tl_set:N    = \l__keythms_storeatbegin_store_tl,
    restate  .meta:n      = { store=#1 },
    store*   .tl_set:N    = \l__keythms_storeatbegin_storereversed_tl,
    restate* .meta:n      = { store*=#1 },
    unknown  .code:n      = { } % do nothing with unknown keys
  }

\cs_new_protected:Npn \KeyThmsContentsLine #1 { #1 }
\NewDocumentCommand \addtheoremcontentsline { m m }
  {
    \addtocontents { thlist }
      {
        \KeyThmsContentsLine
          { % copied from def of \addcontentsline
            \protect\contentsline{#1}{#2}{\thepage}{}
            \protected@file@percent
          }
      }
  }
\NewDocumentCommand \addtotheoremcontents { m }
  {
    \addtocontents { thlist }
      {
        \KeyThmsContentsLine { #1 }
      }
  }

\hook_gput_code:nnn { begindocument } { . }
  {
    \group_begin:
    \cs_set_eq:NN \KeyThmsContentsLine \use_none:n
    \cs_set_eq:NN \KeyThmsAddvspace \use_none:n
    \cs_set_protected:Npn \KeyThmsSavedTheorem #1#2#3#4#5#6#7
      {
        \group_begin:
        \keys_set:nn { keytheorems/storeatbegin } { #6 }
        \tl_if_empty:NF \l__keythms_storeatbegin_store_tl
          {
            \cs_new_protected:cpn
              { __keythms_getthm_ \l__keythms_storeatbegin_store_tl _theorem }
              {
                \__keythms_getthm_theorem:nnnnn
                  {#1}{#2}{#5}{#6}{#7}
              }
            \cs_new_protected:cpn
              { __keythms_getthm_ \l__keythms_storeatbegin_store_tl _body }
              {
                \__keythms_getthm_body:nn {#5}{#7}
              }
          }
        \tl_if_empty:NF \l__keythms_storeatbegin_storereversed_tl
          {
            \tl_const:cn
              { c__keythms_storeatbegin_ \l__keythms_storeatbegin_storereversed_tl _label_tl }
              { #2 }
            \tl_const:cn
              { c__keythms_storeatbegin_ \l__keythms_storeatbegin_storereversed_tl _restatecounters_tl }
              { #5 }
            \cs_new_protected:cpn
              { __keythms_getthm_ \l__keythms_storeatbegin_storereversed_tl _body }
              {
                \__keythms_getthm_body:nn {#5}{#7}
              }
          }
        \group_end:
      }
    \cs_set_protected:Npn \KeyThmsSavedTheoremReversed #1#2#3#4
      {
        \bool_new:c { g__keythms_restate_#1_called_bool }
        \cs_gset:cpn { __keythms_getthm_ #1 _theorem }
          { \__keythms_getthmreversed_theorem:nnn { #2 } { #3 } { #4 } }
        \hook_gput_code:nnn { begindocument/end } { . }
          {
            \cs_if_exist:cF { __keythms_getthm_ #1 _body }
              {
                \cs_new_protected:cpn { __keythms_getthm_ #1 _body }
                  {
                    \textbf{??}
                    \msg_warning:nnn { keytheorems } { restate-body-never-got } { #1 }
                  }
              }
          }
      }
    \file_if_exist_input:n { \c_sys_jobname_str.thlist }
    \group_end:
  }

\prg_new_conditional:Npnn \keythms_if_restating: { T, F, TF }
  {
    \bool_if:NTF \l__keythms_thmuse_restating_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }
\NewDocumentCommand \IfRestatingTF { } { \keythms_if_restating:TF }
\NewDocumentCommand \IfRestatingT { } { \keythms_if_restating:T }
\NewDocumentCommand \IfRestatingF { } { \keythms_if_restating:F }

\cs_new_protected:Npn \__keythms_getthm_theorem:nnnnn #1#2#3#4#5
  { % #1 = name, #2 = number, #3 = restate counters, #4 = keys, #5 = theorem body
    \group_begin:
    \bool_set_true:N \l__keythms_thmuse_restating_bool
    \prop_set_from_keyval:Nn \l__keythms_restate_counters_prop { #3 }
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \tl_set:ce { l_keythms_restate_current_##1_tl } { \the\value{##1} }
        \setcounter { ##1 } { ##2 }
        % ^ FIX: what if eq's numbered by section, theorem, etc.? The
        %        thmtools code is opaque.... Or maybe should be up to the
        %        user to say "restate-counters={section,chapter,...}".
        \cs_set:cpn { theH ##1 }
          { \use:c { the ##1 } . \theHkeythms_restate_dummyctr }
      }
    \tl_if_empty:nTF { #2 }
      { \refstepcounter{keythms_restate_dummyctr} } % for unnumbered theorems
      {
        \cs_set:cpn { the #1 } { #2 }
        \cs_set_eq:cN { c@ #1 } \c@keythms_restate_dummyctr
        \cs_set_eq:cN { theH #1 } \theHkeythms_restate_dummyctr
        % ^ why are the last two lines here? We shouldn't be referencing
        %   restated theorems. Think it's a remnant of thmtools
        % WRONG: needed to make numbering correct after restated theorem.
        % not sure about theH. <- this is needed to prevent duplicate anchors
      }
    \renewcommand\label[2][]{} % disable \label (opt arg in case cleveref loaded)
    \cs_set_eq:NN \ltx@label \use_none:n % disable \ltx@label
    \cs_set_eq:NN \property_record:nn \use_none:nn % disable \RecordProperties
    \cs_set_eq:NN \setuniqmark \use_none:n % work with numbered=unless-unique
    % QUESTION: also disable \hyper@@anchor? \MakeLinkTarget?
    \keys_set:nn { keytheorems/thmuse } { #4 }
    \keys_set:no { keytheorems/thmuse } { \l__keythms_thmuse_restatekeys_clist }
    \hook_use:n { keytheorems/#1/restated }
    \hook_use:n { keytheorems/allthms/restated }
    \__keythms_thm_prehead_continues_code:n { #1 }
    \__keythms_thm_prehead_code:n { #1 }
    \__keythms_orig_begin:nV { #1 } \l__keythms_thmuse_note_tl
    \__keythms_thm_posthead_code:n { #1 }
    #5
    \__keythms_thm_prefoot_code:n { #1 }
    \__keythms_orig_end:n { #1 }
    \__keythms_thm_postfoot_code:n { #1 }
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \exp_args:Nnc \setcounter { ##1 }
          { l_keythms_restate_current_##1_tl }
      }
    \group_end:
  }

\cs_new_protected:Npn \__keythms_getthm_body:nn #1#2
  { % #1 = restate counters, #2 = theorem body
    \group_begin:
    \bool_set_true:N \l__keythms_thmuse_restating_bool
    \prop_set_from_keyval:Nn \l__keythms_restate_counters_prop { #1 }
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \tl_set:ce { l_keythms_restate_current_##1_tl } { \the\value{##1} }
        \setcounter { ##1 } { ##2 }
        % ^ FIX: what if eq's numbered by section, theorem, etc.? The
        %        thmtools code is opaque.... Or maybe should be up to the
        %        user to say "restate-counters={section,chapter,...}".
        \cs_set:cpn { theH ##1 }
          { \use:c { the ##1 } . \theHkeythms_restate_dummyctr }
      }
    \refstepcounter{keythms_restate_dummyctr}
    \renewcommand\label[2][]{} % disable \label (opt arg in case cleveref loaded)
    \cs_set_eq:NN \ltx@label \use_none:n % disable \ltx@label
    \cs_set_eq:NN \property_record:nn \use_none:nn % disable \RecordProperties
    \hook_use:n { keytheorems/#1/restated }
    \hook_use:n { keytheorems/allthms/restated }
    #2
    \prop_map_inline:Nn \l__keythms_restate_counters_prop
      {
        \exp_args:Nnc \setcounter { ##1 }
          { l_keythms_restate_current_##1_tl }
      }
    \group_end:
  }

\cs_new_protected:Npn \__keythms_getthmreversed_theorem:nnn #1#2#3
  { % #1 = envname, #2 = keys, #3 = theorem body
    \group_begin:
    \bool_set_false:N \l__keythms_thmuse_restating_bool
    \keys_set:nn { keytheorems/thmuse } { #2 }
    \keys_set:no { keytheorems/thmuse } { \l__keythms_thmuse_restatekeys_clist }
    \__keythms_thm_prehead_continues_code:n { #1 }
    \__keythms_thm_prehead_code:n { #1 }
    \__keythms_orig_begin:nV { #1 } \l__keythms_thmuse_note_tl
    \clist_map_inline:Nn \g__keythms_restatecounters_clist
      {
        \prop_gput:Nne \g__keythms_thmuse_othercounters_prop { ##1 }
          { \the\value{##1} }
      }
    \__keythms_thm_posthead_code:n { #1 }
    \__keythms_thm_addcontentsdata:nnnn { #1 }
      { \prop_to_keyval:N \g__keythms_thmuse_othercounters_prop }
      { #2 } { #3 }
    \__keythms_thm_tempstorerestatedata:nnn { #1 } { #2 } { #3 } % for defining getthm_body
    #3
    \__keythms_thm_prefoot_code:n { #1 }
    \__keythms_orig_end:n { #1 }
    \__keythms_thm_postfoot_code:n { #1 }
    % While we're here, define getthm_body
    \cs_if_exist:cF
      { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _body }
      {
        \cs_new:cpe
          { __keythms_getthm_ \l__keythms_thmuse_storereversed_tl _body }
          {
            \exp_not:N \__keythms_getthm_body:nn
            \exp_args:No \exp_not:o
              {
                \exp_after:wN \__keythms_use_iii_v_braced:nnnnn
                  \g__keythms_thmuse_temprestatedata_tl
              }
          }
      }
    \bool_gset_true:c
      { g__keythms_restate_ \l__keythms_thmuse_storereversed_tl _called_bool }
    \group_end:
  }

% \getkeytheorem[<property>]{<tag>}
\NewDocumentCommand \getkeytheorem { O{theorem} m }
  {
    \cs_if_exist:cTF { __keythms_getthm_#2_#1 }
      {
        \bool_if_exist:cTF { g__keythms_restate_#2_called_bool }
          {
            \str_if_eq:nnTF { #1 } { theorem }
              {
                \bool_if:cTF
                  { g__keythms_restate_#2_called_bool }
                  {
                    \msg_error:nnn { keytheorems }
                      { store-reversed-called-twice } { #2 }
                  }
                  { \use:c { __keythms_getthm_#2_#1 } }
              }
              { \use:c { __keythms_getthm_#2_#1 } }
          }
          { \use:c { __keythms_getthm_#2_#1 } }
      }
      {
        \textbf{??}
        \cs_if_exist:cTF { __keythms_getthm_#2_theorem }
          {
            \msg_warning:nnnn { keytheorems } { no-prop-for-stored-theorem }
              { #1 } { #2 } % should this be an error?
          }
          { \msg_warning:nnn { keytheorems } { no-stored-theorem } { #2 } }
      }
  }

%%%%%%%%%%%%%%%%%%%%%
%%% Theorem Hooks %%%
%%%%%%%%%%%%%%%%%%%%%

%%% \addtotheoremhook[<envname>]{<hook>}{<code>}
\NewDocumentCommand \addtotheoremhook { O{allthms} m +m }
  {
    \__hook_if_declared:nTF { keytheorems/allthms/#2 }
      {
        \hook_gput_code:nnn { keytheorems/#1/#2 } { . } { #3 }
      }
      {
        \msg_error:nnn { keytheorems } { undefined-thm-hook } { #2 }
      }
  }

% NOTE: I think it's OK we use the internal \__hook_if_declared:nTF above
%       since we don't need to worry about the user creating new theorem hooks
%       so, as we're only checking the existence of hooks created by us, it's OK.

%%%%%%%%%%%%%%%%%%%%%%%%
%%% List of Theorems %%%
%%%%%%%%%%%%%%%%%%%%%%%%

\keys_define:nn { keytheorems/listof }
  {
    numwidth   .dim_set:N = \l__keythms_listof_numwidth_dim,
    numwidth   .initial:n = 2.3em,
    indent     .dim_set:N = \l__keythms_listof_indent_dim,
    indent     .initial:n = 1.5em,
    ignore     .code:n    =
      {
        \hook_gput_code:nnn { begindocument/before } { keytheorems }
          { \keythms_listof_ignore:n { #1 } }
      },
    show       .code:n    =
      {
        \hook_gput_code:nnn { begindocument/before } { keytheorems }
          { \keythms_listof_show:n { #1 } }
      },
    onlynamed  .code:n    =
      {
        \hook_gput_code:nnn { begindocument/before } { keytheorems }
          { \keythms_listof_onlynamed:n { #1 } }
      },
    onlynamed  .default:n = \q_no_value,
    onlynumbered  .code:n    =
      {
        \hook_gput_code:nnn { begindocument/before } { keytheorems }
          { \keythms_listof_onlynumbered:n { #1 } }
      },
    onlynumbered  .default:n = \q_no_value,
    ignoreall  .code:n    =
      {
        \hook_gput_code:nnn { begindocument/before } { keytheorems } % in case called before theorem defined
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_ignore_aux:n { ##1 } }
          }
      },
    showall    .code:n    =
      {
        \hook_gput_code:nnn { begindocument/before } { keytheorems } % in case called before theorem defined
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_show_aux:n { ##1 } }
          }
      },
    title      .tl_set:N   = \l__keythms_listof_title_tl,
    title      .initial:n  = \GetTranslation{keythms_listof_title},
    swapnumber .bool_set:N = \l__keythms_listof_swapnumber_bool,
    swapnumber .initial:n  = false,
    title-code .cs_set:Np  = \__keythms_listof_titlecmd:n #1,
    no-title   .bool_set:N = \l__keythms_listof_notitle_bool,
    no-title   .initial:n  = false,
    print-body .code:n     =
      {
        \cs_set_protected:Nn \keythms_listof_listcmd:nnnnnnn
          {
            \tl_if_empty:nF { ##7 }
              {
                \__keythms_getthm_theorem:nnnnn
                  {##1}{##2}{##5}{##6}{##7}
              }
          }
        \cs_set_eq:NN \KeyThmsContentsLine \use_none:n
        % ^ I assume we want this?
        \cs_set_eq:NN \KeyThmsAddvspace \use_none:n
      },
    note-code  .cs_set:Np = \__keythms_listof_notecmd:n #1,
    note-code  .initial:n = { ~ (#1) },
    no-continues .bool_set:N = \l__keythms_listof_nocont_bool, 
    no-continues .initial:n  = false,
    no-chapter-skip .bool_set:N = \l__keythms_listof_nochapskip_bool,
    no-chapter-skip .initial:n  = false,
    chapter-skip-length .dim_set:N = \keythms@listof@chaptervspace@dim,
    chapter-skip-length .initial:n = 10pt,
    no-toc .bool_set:N = \l__keythms_listof_notoc_bool,
    no-toc .initial:n  = false, % false does not mean "to-toc" for standard classes
  }

\hook_gput_code:nnn { begindocument } { . } % redefine these keys at begindocument
  {
    \keys_define:nn { keytheorems/listof }
      {
        ignore    .code:n    = \keythms_listof_ignore:n { #1 },
        show      .code:n    = \keythms_listof_show:n { #1 },
        onlynamed .code:n    = \keythms_listof_onlynamed:n { #1 },
        onlynamed .default:n = \q_no_value,
        onlynumbered .code:n    = \keythms_listof_onlynumbered:n { #1 },
        onlynumbered .default:n = \q_no_value,
        ignoreall .code:n    =
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_ignore_aux:n { ##1 } }
          },
        showall   .code:n    =
          {
            \prop_map_inline:Nn \g__keythms_thmnames_prop
              { \__keythms_listof_show_aux:n { ##1 } }
          },
        seq       .code:n = \keythms_listof_showseq:n { #1 },
      }
  }

\NewDocumentCommand \keytheoremlistset { m }
  {
    \keys_set:nn { keytheorems/listof } { #1 }
  }

\cs_new_protected:Npn \keythms_listof_ignore:n #1
  {
    \clist_map_inline:nn { #1 } { \__keythms_listof_ignore_aux:n { ##1 } }
  }
\cs_new_protected:Npn \__keythms_listof_ignore_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      { }
  }

\cs_new_protected:Npn \keythms_listof_show:n #1
  {
    \clist_map_inline:nn { #1 } { \__keythms_listof_show_aux:n { ##1 } }
  }
\cs_new_protected:Npn \__keythms_listof_show_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \keythms_listof_listcmd:nnnnnnn
              {#1}{##1}{##2}{##3}{##4}{##5}{##6}
          }
      }
  }

\cs_new_protected:Npn \keythms_listof_onlynamed:n #1
  {
    \quark_if_no_value:nTF { #1 }
      {
        \prop_map_inline:Nn \g__keythms_thmnames_prop
          { \__keythms_listof_onlynamed_aux:n { ##1 } }
      }
      {
        \clist_map_inline:nn { #1 }
          { \__keythms_listof_onlynamed_aux:n { ##1 } }
      }
  }
\cs_new_protected:Npn \__keythms_listof_onlynamed_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \tl_if_empty:NF \l__keythms_listofheading_note_tl
              {
                \keythms_listof_listcmd:nnnnnnn
                  {#1}{##1}{##2}{##3}{##4}{##5}{##6}
              }
          }
      }
  }

\cs_new_protected:Npn \keythms_listof_onlynumbered:n #1
  {
    \quark_if_no_value:nTF { #1 }
      {
        \prop_map_inline:Nn \g__keythms_thmnames_prop
          { \__keythms_listof_onlynumbered_aux:n { ##1 } }
      }
      {
        \clist_map_inline:nn { #1 }
          { \__keythms_listof_onlynumbered_aux:n { ##1 } }
      }
  }
\cs_new_protected:Npn \__keythms_listof_onlynumbered_aux:n #1
  {
    \cs_set_protected:cpn { __keythms_thmitem_#1:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \tl_if_empty:nF { ##1 }
              {
                \keythms_listof_listcmd:nnnnnnn
                  {#1}{##1}{##2}{##3}{##4}{##5}{##6}
              }
          }
      }
  }

\cs_new_protected:Npn \keythms_listof_showseq:n #1
  {
    \prop_map_inline:Nn \g__keythms_thmnames_prop
      { \__keythms_listof_showseq_aux:nn { #1 } { ##1 } }
  }
\cs_new_protected:Npn \__keythms_listof_showseq_aux:nn #1#2
  { % #1 = seq name, #2 = theorem name
    \cs_set_protected:cpn { __keythms_thmitem_#2:nnnnnn } ##1##2##3##4##5##6
      {
        \__keythms_listof_listcmd_setup:nn { ##5 }
          {
            \tl_if_eq:NnT \l__keythms_listofheading_seq_tl { #1 }
              {
                \keythms_listof_listcmd:nnnnnnn
                  {#2}{##1}{##2}{##3}{##4}{##5}{##6}
              }
          }
      }
  }
  
% Seems unnecessary to repeat all this for reading the keyvals from seq.
% In thmtools they just hook the "thmitem" definition into the theorem declaration.
%% NOTE ON ABOVE: this gives more flexibility to define different kinds of lists.
%% See acro.sty for template idea.
\keys_define:nn { keytheorems/listofheading }
  {
    note       .tl_set:N = \l__keythms_listofheading_note_tl,
    name       .meta:n   = { note = #1 },
    short-note .tl_set:N = \l__keythms_listofheading_shortnote_tl,
    short-name .meta:n   = { short-note = #1 },
    continues  .tl_set:N = \l__keythms_listofheading_contlabel_tl,
    continues* .code:n   =
      {
        \keys_set:nn { keytheorems/listofheading } { continues = #1 }
        \protected@edef \l__keythms_tmpa_tl { \__keythms_getrecordednote:n{#1} }
        \tl_if_empty:NF \l__keythms_tmpa_tl
          {
            \keys_set:nn { keytheorems/listofheading }
              { note = \l__keythms_tmpa_tl }
          }
      },
    seq     .tl_set:N = \l__keythms_listofheading_seq_tl,
    store*  .code:n = \bool_set_true:N \l__keythms_listofheading_storereversed_bool,
    restate* .meta:n = { store*=#1 },
    restate-keys .clist_set:N = \l__keythms_listofheading_restatekeys_clist,
    unknown .code:n = { } % do nothing with unknown keys
    % ^ this is OK because we have total control over possible keys; if invalid
    %   key is given to theorem then an error will be raised there
  }

\cs_new:Npn \__keythms_listof_printheading:
  {
    \tl_if_empty:NTF \l__keythms_listofheading_shortnote_tl
      {
        \tl_if_empty:NF \l__keythms_listofheading_note_tl
          { \__keythms_listof_notecmd:n { \l__keythms_listofheading_note_tl } }
      }
      {
        \__keythms_listof_notecmd:n { \l__keythms_listofheading_shortnote_tl }
      }
  }

\cs_new:Npn \__keythms_listof_default_listcmd:nnnnnnn #1#2#3#4#5#6#7
  {
    \contentsline{ #1 }
      {
        \bool_if:NTF \l__keythms_listof_swapnumber_bool
          {
            \prop_item:Nn \g__keythms_thmnames_prop { #1 } ~ #2
          }
          {
            \numberline{ #2 }
            \prop_item:Nn \g__keythms_thmnames_prop { #1 }
          }
        \__keythms_listof_printheading:
      }
      { #4 }{ #3 }
  }

% NOTE: We still need to do this setup for [print-body] so that onlynamed works
\cs_new_protected:Npn \__keythms_listof_listcmd_setup:nn #1#2
  { % #1 = keys, #2 = list command
    \group_begin:
    \keys_set:nn { keytheorems/listofheading } { #1 }
    \bool_if:NT \l__keythms_listofheading_storereversed_bool
      {
        \keys_set:no { keytheorems/listofheading }
          { \l__keythms_listofheading_restatekeys_clist }
      }
    \tl_if_empty:NTF \l__keythms_listofheading_contlabel_tl
      { #2 }
      {
        \bool_if:NF \l__keythms_listof_nocont_bool
          {
            \tl_if_empty:NF \l__keythms_listofheading_note_tl
              {
                \tl_put_right:Nn \l__keythms_listofheading_note_tl { , ~ }
              }
            \tl_put_right:Nn \l__keythms_listofheading_note_tl
              {
                \__keythms_thmuse_continues:V \l__keythms_listofheading_contlabel_tl
              }
            #2
          }
      }
    \group_end:
  }

% set default listcmd
\cs_new_eq:NN \keythms_listof_listcmd:nnnnnnn
  \__keythms_listof_default_listcmd:nnnnnnn

\cs_if_exist:NTF \chapter
  { \cs_set_protected:Npn \__keythms_listof_titlecmd:n #1 { \chapter*{#1} } }
  { \cs_set_protected:Npn \__keythms_listof_titlecmd:n #1 { \section*{#1} } }

\cs_new_protected:Npn \__keythms_listof_default_tocline:
   {
     \@dottedtocline{ 1 }{ \l__keythms_listof_indent_dim }
       { \l__keythms_listof_numwidth_dim }
   }
\cs_new_eq:NN \keythms_listof_tocline: \__keythms_listof_default_tocline:

\NewDocumentCommand \listofkeytheorems { O{} }
  {
    \bool_gset_true:N \g__keythms_listof_writefile_bool
    \group_begin:
    \keys_set:nn { keytheorems/listof } { #1 }
    \bool_if:NT \l__keythms_listof_nochapskip_bool
      {
        \cs_set_eq:NN \KeyThmsAddvspace \use_none:n
      }
    \bool_if:NF \l__keythms_listof_notitle_bool
      {
        \__keythms_listof_titlecmd:n { \l__keythms_listof_title_tl }
        \@mkboth % QUESTION: should this go in titlecmd ?
          { \MakeUppercase \l__keythms_listof_title_tl }
          { \MakeUppercase \l__keythms_listof_title_tl }
      }
    \legacy_if_set_false:n { @filesw }
    \@starttoc{ thlist }
    \group_end:
  }
% ^ unlike thmtools we don't use the class's style of \listoffigures because
%   we want control over title-code, no-title, etc. But this means we have to guess
%   things like marks, sectioning command, etc.

\hook_gput_code:nnn { enddocument } { . }
  {
    \bool_if:NTF \g__keythms_listof_writefile_bool
      {
        \legacy_if:nT { @filesw }
          {
            \iow_new:N \tf@thlist
            \iow_open:Nn \tf@thlist { \c_sys_jobname_str.thlist }
          }
      }
      { % if .thlist file left over from previous run but not needed, clear it
        \file_if_exist:nT { \c_sys_jobname_str.thlist }
          {
            \iow_open:Nn \g_tmpa_iow { \c_sys_jobname_str.thlist }
            \iow_close:N \g_tmpa_iow
          }
      }
  }

% chaptervspacehack (code translated from thmtools)
\cs_new_eq:NN \KeyThmsAddvspace \addvspace
\int_new:N \g_keythms_listof_prevchapter_int
\int_gset:Nn \g_keythms_listof_prevchapter_int { 1 }
% ^ if this is zero, bad things happen if title-code is changed; anyways don't
%   need addvspace at top
\cs_new_protected:Npn \keythms_listof_chaptervspacehack: { }
\cs_if_exist:cT { c@chapter }
  {
    \cs_if_eq:NNF \c@chapter \relax
      {
        \cs_set_protected:Npn \keythms_listof_chaptervspacehack:
          {
            \int_compare:nNnF
              { \value{chapter} } = { \g_keythms_listof_prevchapter_int }
              {
                \addtocontents{ thlist }
                  {
                    \protect\KeyThmsAddvspace
                      { \keythms@listof@chaptervspace@dim }
                  }
                \int_gset:Nn \g_keythms_listof_prevchapter_int { \value{chapter} }
              }
          }
      }
  }

%%%%%%%%%%%%%%%%
%%% \Autoref %%%
%%%%%%%%%%%%%%%%

\ProvideDocumentCommand { \Autoref } { s m }
  {
    \IfPackageLoadedTF { hyperref }
      {
        \group_begin:
        \cs_set_eq:NN \HyRef@testreftype \__keythms_Autoref_testreftype:w
        \IfBooleanTF { #1 } { \autoref*{#2} } { \autoref{#2} }
        \group_end:
      }
      { \msg_error:nn { keytheorems } { hyperref-Autoref } }
  }

\cs_new_protected:Npn \__keythms_Autoref_testreftype:w #1.#2\\
  {
    \cs_if_exist:cTF { #1 Autorefname }
      {
        \cs_set:Npe \HyRef@currentHtag
          {
            \exp_not:N \use:c { #1 Autorefname }
            \exp_not:N \c_space_token
          }
      }
      { \msg_warning:nnn { keytheorems } { no-Autorefname } { #1 } }
  }

%%%%%%%%%%%%%%%%%%%
%%% Global Keys %%%
%%%%%%%%%%%%%%%%%%%

\keys_define:nn { keytheorems }
  {
    restate-counters .code:n =
      {
        \clist_map_inline:nn { #1 }
          { \tl_new:c { l_keythms_restate_current_##1_tl } }
        \clist_gput_right:Nn \g__keythms_restatecounters_clist { #1 }
      },
    restate-counters .initial:n = equation,
    continues-code   .cs_set:Np = \__keythms_thmuse_continues:n #1,
    continues-code   .initial:n =
      { % not sure how best to handle this translation
        \GetTranslation{keythms_continues}\pageref{#1}
      },
    qed-symbol       .cs_set_protected:Np = \qedsymbol,
    overload         .code:n = \__keythms_overload_code:,
    overload         .value_forbidden:n = true,
    overload         .usage:n = preamble,
    thmtools-compat  .code:n =
      { % prevent loading the code again if key called twice
        \bool_if:NF \g__keythms_thmtoolscompat_bool
          { \__keythms_thmtoolscompat_code: }
      },
    thmtools-compat  .value_forbidden:n = true,
    thmtools-compat  .usage:n = preamble,
    store-all        .code:n = \__keythms_storeall_code:,
    store-all        .value_forbidden:n = true,
    store-all        .usage:n = preamble,
    auto-translate   .bool_gset:N = \g__keythms_autotranslate_bool,
    auto-translate   .initial:n = true,
    store-sets-label .code:n =
      {
        \keys_define:nn { keytheorems/thmuse }
          {
            store .code:n =
              {
                \tl_set:Nn \l__keythms_thmuse_label_tl { ##1 }
                \tl_set:Nn \l__keythms_thmuse_store_tl { ##1 }
              },
            store* .code:n =
              {
                \tl_set:Nn \l__keythms_thmuse_label_tl { ##1 }
                \tl_set:Nn \l__keythms_thmuse_storereversed_tl { ##1 }
              },
          }
      },
  }

\cs_generate_variant:Nn \__keythms_thmuse_continues:n { V }

% \keytheoremset{<options>}
\NewDocumentCommand \keytheoremset { m }
  {
    \keys_set:nn { keytheorems } { #1 }
  }

\cs_new_protected:Npn \__keythms_overload_code:
  {
    \RenewDocumentCommand { \newtheorem } { s m o m o }
      {
        \IfBooleanTF { ##1 }
          { \keythms_thm_newkeythm:nn { ##2 } { name=##4, numbered=no } }
          {
            \IfNoValueTF { ##3 }
              {
                \IfNoValueTF { ##5 }
                  { \keythms_thm_newkeythm:nn { ##2 } { name=##4 } }
                  { \keythms_thm_newkeythm:nn { ##2 } { name=##4, parent=##5 } }
              }
              { \keythms_thm_newkeythm:nn { ##2 } { name=##4, sibling=##3 } }
          }
      }
  }

\cs_new_protected:Npn \__keythms_thmtoolscompat_code:
  {
    \bool_gset_true:N \g__keythms_thmtoolscompat_bool
    \__keythms_overload_code: % since thmtools overwrites \newtheorem
    \ProvideDocumentCommand { \declaretheoremstyle } { O{} m }
      {
        \declarekeytheoremstyle { ##2 } { ##1 }
      }
    \ProvideDocumentCommand { \declaretheorem } { O{} m }
      {
        \newkeytheorem { ##2 } [ ##1 ]
      }
    \ProvideDocumentEnvironment { restatable } { O{} m m }
      { % need to redefine this to add store to thlist since we set it outside env
        \cs_set_protected:Npn \__keythms_thm_addcontentsdata:nnnn ####1####2####3####4
          { % #1 = theorem name, #2 = stored counters, #3 = keys, #4 = body
            \keythms_listof_chaptervspacehack:
            \iow_shipout:Ne \@auxout
              {
                \exp_not:N \@writefile { thlist }
                  {
                    \KeyThmsSavedTheorem{ ####1 }
                      { \@currentlabel }
                      { \@currentHref }
                      { \thepage }
                      { ####2 }
                      { store=\l__keythms_thmuse_store_tl,\exp_not:n { ####3 } } % this line is changed
                      { \exp_not:n { ####4 } }
                  }
              }
          }
        % set store outside [] so keyless note is recognized
        \keys_set:nn { keytheorems/thmuse } { store=##3 }
        \begin{##2}[##1]
      }
      {
        \end{##2}
        \cs_new_protected:cpn { ##3 }
          { % make \foo and \foo* identical
            \peek_meaning_remove:NTF *
              { \getkeytheorem{ ##3 } }
              { \getkeytheorem{ ##3 } }
          }
      }
    \ProvideDocumentEnvironment { restatable* } { O{} m m }
      { % need to redefine this to add store* to thlist since we set it outside env
        \cs_set_protected:Npn \__keythms_thm_addstoredreverseddata:nnn ####1####2####3
          {
            \iow_shipout:Ne \@auxout
              {
                \exp_not:N \@writefile { thlist }
                  {
                    \KeyThmsSavedTheoremReversed { \l__keythms_thmuse_storereversed_tl }
                      { ####1 }
                      { store*=\l__keythms_thmuse_storereversed_tl,\exp_not:n { ####2 } } % this line is changed
                      { \exp_not:n { ####3 } }
                  }
              }
          }
        % set store* outside [] so keyless note is recognized
        \keys_set:nn { keytheorems/thmuse } { store*=##3 }
        \begin{##2}[##1]
      }
      {
        \end{##2}
        \cs_new_protected:cpn { ##3 }
          { % make \foo and \foo* identical
            \peek_meaning_remove:NTF *
              { \getkeytheorem{ ##3 } }
              { \getkeytheorem{ ##3 } }
          }
      }
    \ProvideDocumentCommand { \listoftheorems } { } { \listofkeytheorems }
    \ProvideDocumentCommand { \addtotheorempreheadhook } { O{allthms} m }
      {
        \addtotheoremhook [ ##1 ] { prehead } { ##2 }
      }
    \ProvideDocumentCommand { \addtotheorempostheadhook } { O{allthms} m }
      {
        \addtotheoremhook [ ##1 ] { posthead } { ##2 }
      }
    \ProvideDocumentCommand { \addtotheoremprefoothook } { O{allthms} m }
      {
        \addtotheoremhook [ ##1 ] { prefoot } { ##2 }
      }
    \ProvideDocumentCommand { \addtotheorempostfoothook } { O{allthms} m }
      {
        \addtotheoremhook [ ##1 ] { postfoot } { ##2 }
      }
    \clist_new:N \l__keythms_tcbshaded_keys_clist
    \clist_new:N \l__keythms_tcbthmbox_keys_clist
    \keys_define:nn { keytheorems/thm/shaded }
      {
        textwidth   .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { width=##1 },
        bgcolor     .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { colback=##1 },
        rulewidth   .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { boxrule=##1 },
        rulecolor   .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { colframe=##1 },
        margin      .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { boxsep=##1 },
        padding     .meta:n = { margin=##1 },
        leftmargin  .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { left~skip=##1 },
        rightmargin .code:n =
          \clist_put_right:Nn \l__keythms_tcbshaded_keys_clist { right~skip=##1 },
      }
    \keys_define:nn { keytheorems/thm/thmbox }
      {
        L .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { keythms_tcbthmbox_L }
          },
        M .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { keythms_tcbthmbox_M }
          },
        S .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { keythms_tcbthmbox_S }
          },
        underline .choice:,
        underline / true .code:n = {},
        underline / false .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist
              { boxed~title~style={bottomrule=0pt} }
          },
        underline .default:n = true,
        nounderline .meta:n = { underline=false },
        cut .choice:,
        cut / true .code:n = {},
        cut / false .code:n =
          {
            \clist_put_right:Nn \l__keythms_tcbthmbox_keys_clist { unbreakable }
          },
        cut .default:n = true,
        nocut .meta:n = { cut=false },
        thickness .code:n = % could also add keys to clist with changed dimens; which is better?
          {
            \hook_gput_code:nnn { keytheorems/\l__keythms_thm_envname_tl/prehead }
              { keythms_tcbox }
              { \dim_set:Nn \l_keythms_tcbthmbox_thickness_dim { ##1 } }
          },
        leftmargin .code:n =
          {
            \hook_gput_code:nnn { keytheorems/\l__keythms_thm_envname_tl/prehead }
              { keythms_tcbox }
              { \dim_set:Nn \l_keythms_tcbthmbox_leftmargin_dim { ##1 } }
          },
        rightmargin .code:n =
          {
            \hook_gput_code:nnn { keytheorems/\l__keythms_thm_envname_tl/prehead }
              { keythms_tcbox }
              { \dim_set:Nn \l_keythms_tcbthmbox_rightmargin_dim { ##1 } }
          },
        hskip .code:n =
          {
            \hook_gput_code:nnn { keytheorems/\l__keythms_thm_envname_tl/prehead }
              { keythms_tcbox }
              { \dim_set:Nn \l_keythms_tcbthmbox_hskip_dim { ##1 } }
          },
        vskip .code:n =
          {
            \hook_gput_code:nnn { keytheorems/\l__keythms_thm_envname_tl/prehead }
              { keythms_tcbox }
              { \dim_set:Nn \l_keythms_tcbthmbox_vskip_dim { ##1 } }
          },
      }
    \dim_new:N \l_keythms_tcbthmbox_thickness_dim
    \dim_set:Nn \l_keythms_tcbthmbox_thickness_dim { 0.6pt }
    \dim_new:N \l_keythms_tcbthmbox_leftmargin_dim
    \dim_set:Nn \l_keythms_tcbthmbox_leftmargin_dim { 0.7\parindent } % use \parindent? thmbox does
    \dim_new:N \l_keythms_tcbthmbox_rightmargin_dim
    \dim_set:Nn \l_keythms_tcbthmbox_rightmargin_dim { 0pt }
    \dim_new:N \l_keythms_tcbthmbox_hskip_dim
    \dim_set:Nn \l_keythms_tcbthmbox_hskip_dim { 0.2em }
    \dim_new:N \l_keythms_tcbthmbox_vskip_dim
    \dim_set:Nn \l_keythms_tcbthmbox_vskip_dim { 0.2em }
    \msg_new:nnn { keytheorems } { mdframed-undefined }
      {
        keytheorems~does~not~define~the~'mdframed'~key.~
        Consider~using~the~'tcolorbox'~key~instead.
      }
    \keys_define:nn { keytheorems/thm }
      {
        shaded .code:n =
          {
            \clist_clear:N \l__keythms_tcbshaded_keys_clist
            \keys_set:nn { keytheorems/thm/shaded } { ##1 }
            % FIX: surely a better way to do this
            \RequirePackage{tcolorbox}
            \pgfkeysifdefined{/tcb/keythms_tcbshaded_default/.@cmd} % even worth it?
              {}
              {
                \tcbset % wish I could do this outside of key but can't assume tcb loaded
                  {
                    keythms_tcbshaded_default/.style=
                      {
                        sharp~corners = all,
                        boxrule = 0pt,
                        left = 0pt, right = 0pt,
                        top = 0pt, bottom = 0pt,
                        parbox = false,
                      }
                  }
              }
            \keys_set:ne { keytheorems/thm }
              {
                tcolorbox-no-titlebar =
                  {
                    keythms_tcbshaded_default,
                    \l__keythms_tcbshaded_keys_clist
                  }
              }
          },
        thmbox .code:n = % adapted from https://tex.stackexchange.com/a/236230/208544
          {
            \clist_clear:N \l__keythms_tcbthmbox_keys_clist
            \keys_set:nn { keytheorems/thm/thmbox } { ##1 }
            % FIX: surely a better way to do this
            \RequirePackage{tcolorbox}
            \tcbuselibrary{skins,breakable}
            \pgfkeysifdefined{/tcb/keythms_tcbthmbox_default/.@cmd} % even worth it?
              {}
              {
                \tcbset{
                  keythms_tcbthmbox_default/.style={
                    enhanced,
                    breakable,
                    sharp~corners=all,
                    right=\l_keythms_tcbthmbox_hskip_dim,
                    left=\l_keythms_tcbthmbox_hskip_dim,
                    top=\l_keythms_tcbthmbox_vskip_dim,
                    bottom=\l_keythms_tcbthmbox_vskip_dim,
                    coltitle=black,
                    frame~engine=empty,
                    interior~titled~engine=empty,
                    interior~engine=empty,
                    extras~broken={
                      frame~engine=empty,
                      interior~titled~engine=empty,
                      interior~engine=empty
                      },
                    parbox=false,
                    % even though frame isn't drawn, makes spacing correct
                    boxrule=0.5\l_keythms_tcbthmbox_thickness_dim,
                    attach~boxed~title~to~top~left={
                      xshift=-\l_keythms_tcbthmbox_leftmargin_dim,
                      },
                    boxed~title~style={
                      empty,
                      size=minimal,
                      bottom=0.3ex,
                      top=0ex,
                      % ditto
                      bottomrule=0.5\l_keythms_tcbthmbox_thickness_dim,
                      },
                    left~skip=\l_keythms_tcbthmbox_leftmargin_dim,
                    right~skip=\l_keythms_tcbthmbox_rightmargin_dim,
                    overlay~unbroken={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        ([xshift=10mm]frame.south~west);
                      },
                    overlay~first={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      },
                    overlay~middle={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      },
                    overlay~last={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        ([xshift=10mm]frame.south~west);
                      }
                    },
                  keythms_tcbthmbox_L/.style={
                    overlay~unbroken={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        (frame.south~east)
                        -|
                        (frame.north~east);
                      },
                    overlay~first={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~east)
                        --
                        (frame.south~east);
                      },
                    overlay~middle={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~east)
                        --
                        (frame.south~east);
                      },
                    overlay~last={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        |-
                        (frame.south~east)
                        -|
                        (frame.north~east);
                      }
                    },
                  keythms_tcbthmbox_M/.style={},
                  keythms_tcbthmbox_S/.style={ % first and middle same as M
                    overlay~unbroken={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (title.south~west)
                        --
                        (title.south~east);
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      },
                    overlay~last={
                      \draw[line~width=\l_keythms_tcbthmbox_thickness_dim]
                        (frame.north~west)
                        --
                        (frame.south~west);
                      }
                    },
                  }
              }
            \keys_set:ne { keytheorems/thm }
              {
                tcolorbox =
                  {
                    keythms_tcbthmbox_default,
                    \l__keythms_tcbthmbox_keys_clist
                  }
              }
          },
        thmbox .default:n = M,
        mdframed .code:n = \msg_error:nn { keytheorems } { mdframed-undefined },
      }
    \keys_define:nn { keytheorems/thmstyle }
      {
        shaded .code:n = \keythms_thmstyle_savethmkey_optval:n { ##1 },
        thmbox .code:n = \keythms_thmstyle_savethmkey_optval:n { ##1 },
      }
  }

\cs_new_protected:Npn \__keythms_storeall_code:
  {
    \cs_set_eq:NN \__keythms_withhooks_begin:nnn \__keythms_grab_begin:nnn
    \cs_set_eq:NN \__keythms_withhooks_begin:nnV \__keythms_grab_begin:nnV
    \cs_set_eq:NN \__keythms_withhooks_end:n \__keythms_grab_end:n
  }

\hook_gput_code:nnn { begindocument/before } { . }
  { % use 'provide' in case user defines their own translation in preamble
    \ProvideTranslationFallback { keythms_listof_title } { List~of~Theorems }
    \ProvideTranslationFallback { keythms_continues } { continuing~from~p.\, }
    \bool_if:NT \g__keythms_autotranslate_bool
      {
        \ProvideTranslation { English } { keythms_listof_title } { List~of~Theorems }
        \ProvideTranslation { English } { keythms_continues } { continuing~from~p.\, }
        % from DeepL; I don't know these languages!
        \ProvideTranslation { French } { keythms_listof_title } { Liste~des~théorèmes }
        \ProvideTranslation { French } { keythms_continues } { suite~de~la~p.\, }
        \ProvideTranslation { German } { keythms_listof_title } { Liste~der~Theoreme }
        \ProvideTranslation { German } { keythms_continues } { weiter~von~Seite~ }
        \ProvideTranslation { Italian } { keythms_listof_title } { Elenco~dei~teoremi }
        \ProvideTranslation { Italian } { keythms_continues } { continua~da~p.\, }
        \ProvideTranslation { Spanish } { keythms_listof_title } { Lista~de~teoremas }
        \ProvideTranslation { Spanish } { keythms_continues } { continúa~de~la~p.\, }
        \ProvideTranslation { Portuguese } { keythms_listof_title } { Lista~de~teoremas }
        \ProvideTranslation { Portuguese } { keythms_continues } { continua~da~p.\, }
      }
  }

\ProcessKeyOptions[keytheorems]

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support for non-default classes %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\cs_new_protected:Npn \__keythms_support_AMSshared_code:
  {
    \keys_define:nn { keytheorems/listof } % adjust to AMS classes
      {
        numwidth   .initial:n = 1.5pc,
        indent     .initial:n = 0pt,
        title-code .code:n    =
          { % warn but set titlecmd just in case
            \msg_warning:nn { keytheorems } { title-code-with-AMS }
            \cs_set_protected:Npn \__keythms_listof_titlecmd:n ####1 { ##1 }
          },
      }
    \RenewDocumentCommand \listofkeytheorems { O{} }
      { % title command not customizable here
        \bool_gset_true:N \g__keythms_listof_writefile_bool
        \group_begin:
        \keys_set:nn { keytheorems/listof } { ##1 }
        \bool_if:NT \l__keythms_listof_nochapskip_bool
          {
            \cs_set_eq:NN \KeyThmsAddvspace \use_none:n
          }
        \legacy_if_set_false:n { @filesw }
        \bool_if:NTF \l__keythms_listof_notitle_bool
          { % hacky!
            \cs_set_eq:NN \@startsection \use_none:nnnnnnn
            \@starttoc{ thlist }{ }
          }
          { % ams classes don't expand title enough
            \protected@edef \l__keythms_tmpa_tl { \l__keythms_listof_title_tl }
            \bool_if:NT \l__keythms_listof_notoc_bool
              { \cs_set_eq:NN \addcontentsline \use_none:nnn } % hacky!
            \@starttoc{ thlist }{ \l__keythms_tmpa_tl }
          }
        \group_end:
      }
    \cs_new:Npn \__keythms_listof_ams_tocline:
      {
        \@tocline{ 0 }{ 3pt plus 2pt }{ \l__keythms_listof_indent_dim }
          { \l__keythms_listof_numwidth_dim }{ }
      }
    \cs_set_eq:NN \keythms_listof_tocline: \__keythms_listof_ams_tocline:
  }

\cs_new_protected:Npn \keythms_support_check:n #1
  {
    \IfClassLoadedT { #1 } { \file_input:n { class-support/keythms-#1-support } }
  }

% acmart defaults also handled in amsart support file
\keythms_support_check:n { amsart }
\keythms_support_check:n { amsbook }
\keythms_support_check:n { amsproc }
\keythms_support_check:n { memoir }

\file_input_stop: