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}
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

  • 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 '18 at 9:51
  • 1
    @Manuel No precise reason. I felt it's cleaner this way. – egreg May 24 '18 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 '18 at 12:43
  • @ar2015 Update your TeX distribution. – egreg May 24 '18 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 '18 at 13:00

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.