4

I'm trying to use a property list from expl3 however, I have a very simple example that fails. Can anyone help me understand my error?

\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn
% define a propery list
\prop_new:N \my_tooltip_prop
%
\NewDocumentCommand{\CSetA}{mm}{
    \prop_gput:Nnn \my_tooltip_prop {#1} {#2}
}
%
\NewDocumentCommand{\CGetA}{m}{
    \prop_get:NnN \my_tooltip_prop {#1}
}
%
%
% Altenative
%
\cs_new_protected:Npn \CSetB #1#2 {
    \prop_gput:Nnn \my_tooltip_prop {#1} {#2}
}
%
\cs_new:Npn \CGetB #1 {
    \prop_get:NnN \my_tooltip_prop {#1}
}
\ExplSyntaxOff

\begin{document}
\pagestyle{empty}

Hello

%\CSetA{key1}{value1}
%\CGetA{key1} % same error as with \CGetB{key2}

\CSetB{key2}{value2}
\CGetB{key2}

\end{document}

The error message is

! TeX capacity exceeded, sorry [main memory size=5000000].
\par ->valu
           e2
l.40 \end{document}

My system is running Kubuntu 16.10.

  • 3
    \prop_get:NnN needs three arguments – you only have two! – clemens Dec 14 '16 at 10:12
  • 1
    Use \prop_item:Nn instead of \prop_get:NnN. – Henri Menke Dec 14 '16 at 10:41
  • Thank you, you are right! \prop_item:Nn is not defined anymore :( I had to change \CGetA and \CGetB to: \prop_get:NnN \my_tooltip_prop {#1} \tempVar \tempVar – João Leal Dec 14 '16 at 11:10
4

The correct way is with \prop_item:Nn:

\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn
% define a propery list
\prop_new:N \g_leal_tooltip_prop
%
\NewDocumentCommand{\CSet}{mm}
 {
  \prop_gput:Nnn \g_leal_tooltip_prop {#1} {#2}
 }
%
\NewDocumentCommand{\CGet}{m}
 {
  \prop_item:Nn \g_leal_tooltip_prop {#1}
 }
\ExplSyntaxOff

\begin{document}
\pagestyle{empty}

Hello

\CSet{key1}{value1}
\CGet{key1}

\CSet{key2}{value2}
\CGet{key2}

\end{document}

The \prop_item:Nn function has been introduced on 2014-07-17; if you get it is undefined, your TeX distribution is lagging behind.

An almost equivalent version would be with the help of a token list variable:

\tl_new:N \l_leal_tooltip_temp_tl
\NewDocumentCommand{\CGet}{m}
 {
  \prop_get:NnN \g_leal_tooltip_prop {#1} \l_leal_tooltip_temp_tl
  \tl_use:N \l_leal_tooltip_temp_tl
 }
  • This »almost equivalent« version of \prop_item:Nn is not fully expandable. It should be fairly easy to backport \prop_item:Nn. It’s only a few lines. – Henri Menke Dec 14 '16 at 12:37
  • @HenriMenke Yes, I used “almost” on purpose. I'd prefer to update the TeX distribution rather than hacking. – egreg Dec 14 '16 at 12:39
  • Thank you! My version of expl3 is from 2016/05/18 (v6512). I had previously used \prop_item:Nn but then it stopped working after an upgrade (Undefined control sequence). – João Leal Dec 15 '16 at 13:15
  • @egreg : Can you replace \tl_new:Nn for \tl_new:N?, just with the idea of keeping the answer updated, Saludos – Pablo González L Jun 25 at 3:46
1

In ConTeXt you get property lists with a high-level interface.

\starttext

\setvariables
  [tooltip]
  [
    key1=value1,
    key2=value2,
  ]

\getvariable{tooltip}{key1}
\getvariable{tooltip}{key2}

\stoptext
  • Interestingly, we're currently discussing the link between property lists and keyval methods on the LaTeX team list :) – Joseph Wright Dec 14 '16 at 12:56
0

You can achieve something similar to my ConTeXt answer with LuaLaTeX. To parse the key-value list, I still use utilities.parsers.settings_to_hash from ConTeXt. To do so, I have to import the necessary ConTeXt core files, namely

dofile(kpse.find_file("l-lpeg.lua"))
dofile(kpse.find_file("util-sto.lua"))
dofile(kpse.find_file("util-prs.lua"))

The following code is very generic and has an interface similar to the ConTeXt version. It should be easy to repurpose it.

\documentclass{article}

\directlua{
dofile(kpse.find_file("l-lpeg.lua"))
dofile(kpse.find_file("util-sto.lua"))
dofile(kpse.find_file("util-prs.lua"))

uservariables         = uservariables or {}
uservariables.content = uservariables.content or {}

function uservariables.put(namespace,keyvals)
    local input = utilities.parsers.settings_to_hash(keyvals)

    uservariables.content[namespace] = uservariables.content[namespace] or {}

    for k,v in pairs(input) do
        uservariables.content[namespace][k] = v
    end
end

function uservariables.get(namespace,k) 
    tex.sprint(uservariables.content[namespace][k] or "")
end
}

\newcommand\setvariables[2]{%
  \directlua{uservariables.put(\unexpanded{[==[#1]==], [==[#2]==]})}}

\newcommand\getvariable[2]{%
  \directlua{uservariables.get(\unexpanded{[==[#1]==], [==[#2]==]})}}

\begin{document}

\setvariables
  {tooltip}
  {
    key1=value1,
    key2=value2,
  }

\getvariable{tooltip}{key1}
\getvariable{tooltip}{key2}

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.