5

This question comes from combination of two previous questions A and B which worked properly without any problem. But it fails when I combine them.

I have a result file

results/measurements.txt

length1=0.111111111
length2=0.123456789
length3=0.333333333

And I would like to call it in my code as

\paraminput[length2]{results.txt}

It reads the file and extract the result. It works fine except for 0.123456789 is too long and I do not like to touch the result file because it should be updated everytime and I cannot always keep editing it.

So I need another command to perform rounding. So the defined command \round[2]{0.123456789} also works fine. It prints what it should.

The problem is with when I combine them as

 \round[2]{\paraminput[length2]{results.txt}}

It does not work and it give an error:

Missing \endcsname inserted. ...2]{\paraminput[length2]{measurements.txt}}

...

LaTeX error: "kernel/file-not-found" File '"results/\endcsname "' not found. For immediate help type H . ...2]{\paraminput[length2]{measurements.txt}}

,

Undefined control sequence. ...2]{\paraminput[length2]{measurements.txt}}

How should I fix this problem?

source.tex

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse} % for paraminput

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\round}[2][2]{
    \pgfkeys{/pgf/number format/.cd,std,precision=#1}
    \pgfmathprintnumber{#2}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExplSyntaxOn

\ior_new:N \ar_param_file

\seq_new:N \g_ar_param_seq


\cs_new:Nn \ar_read_by_line:n {%
    \seq_gput_right:Nn \g_ar_param_seq {#1}
}

\tl_new:N \g_paramfile_path_tl

\NewDocumentCommand{\parampath}{m}{%
    \tl_gset:Nn \g_paramfile_path_tl {#1}
}

\NewDocumentCommand{\paraminput}{O{default1}  m}{%
    \seq_gclear:N \g_ar_param_seq
    \ior_open:Nn \ar_param_file {\g_paramfile_path_tl #2}
    \ior_map_inline:Nn \ar_param_file {\ar_read_by_line:n{##1}}
    \ior_close:N \ar_param_file
    \seq_map_inline:Nn \g_ar_param_seq {%
        \seq_set_split:Nnn \l_tmpa_seq {=} {##1}
        \seq_if_in:NxT \l_tmpa_seq {#1} {\seq_item:Nn \l_tmpa_seq {2}\seq_map_break:}
    }
}


\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\parampath{results/}

\begin{document}
It shows fine: $\paraminput[length2]{measurements.txt}$.

It shows fine: $\round[2]{0.123456789}$.

But this one shows error: $\round[2]{\paraminput[length2]{measurements.txt}}$.
\end{document}
0

1 Answer 1

3

The operation \paraminput is not expandable, so you cannot pass it to \round.

I suggest to split the operation into first loading the values from the file and then using \getparam for retrieving a value.

\begin{filecontents*}{\jobname.txt}
length1=0.111111111
length2=0.123456789
length3=0.333333333
\end{filecontents*}

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\ior_new:N \ar_param_stream
\clist_new:N \l_ar_param_clist
\tl_new:N \l_ar_param_path_tl
\prop_new:N \l_ar_param_prop

\cs_generate_variant:Nn \prop_set_from_keyval:Nn { NV }

\NewDocumentCommand{\parampath}{m}
 {
    \tl_set:Nn \l_ar_param_path_tl {#1}
 }

\NewDocumentCommand{\paraminput}{O{default}m}
 {
    \clist_clear:N \l_ar_param_seq
    \ior_open:Nn \ar_param_stream {\l_ar_param_path_tl #2}
    \ior_map_inline:Nn \ar_param_stream { \clist_put_right:Nn \l_ar_param_clist { ##1 } }
    \ior_close:N \ar_param_stream
    \prop_set_from_keyval:NV \l_ar_param_prop \l_ar_param_clist
    \prop_clear_new:c { l_ar_param_#1_prop }
    \prop_set_eq:cN  { l_ar_param_#1_prop } \l_ar_param_prop
 }

\NewExpandableDocumentCommand{\getparam}{O{default}m}
 {
    \prop_item:cn { l_ar_param_#1_prop } { #2 }
 }
\NewExpandableDocumentCommand{\round}{O{5}m}
 {
    \fp_eval:n { round(#2,#1) }
 }

\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%\parampath{results/} % non subdirectory for me

\begin{document}

% read a file and store the values
\paraminput{\jobname.txt}

It shows fine: $\getparam{length2}$.

It shows fine: $\round[2]{0.123456789}$.

It shows fine: $\round[2]{\getparam{length2}}$

\end{document}

You can have as many parameter files as you want, just load them with

\paraminput[<symbolic name>]{<filename>}

and retrieve a value with

\getparam[<symbolic name>]{<parameter name>}

enter image description here

7
  • Why did you choose \prop_set_from_keyval:NV and then \prop_set_eq:cN rather than just having :cV in the first command?
    – Manuel
    May 24, 2018 at 9:51
  • 1
    @Manuel No precise reason. I felt it's cleaner this way.
    – egreg
    May 24, 2018 at 9:57
  • How to get around this error? LaTeX error: "kernel/command-not-defined" ! ! Control sequence \prop_set_from_keyval:Nn undefined.
    – ar2015
    May 24, 2018 at 12:43
  • @ar2015 Update your TeX distribution.
    – egreg
    May 24, 2018 at 12:44
  • Using \DeclareExpandableDocumentCommand instead of \NewExpandableDocumentCommand fixes some of the errors but not all. Upgrading will be a trouble and the target journal will face with an error. I cannot ask them to update their latex version. Are these features replaceable with the older versions?
    – ar2015
    May 24, 2018 at 13:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .