
서식 지정과 계산을 위해 데이터를 조작할 수 있도록 다음과 같은 유형의 여러 데이터 조각을 저장하고 싶습니다. 사용자 코드에서 분석되는 라인 수는 미리 정해져 있지 않습니다.
나는 이미 이 값을 추출하는 파서를 만들었습니다.
LINE: 1
CTXT: xvals
LABEL: t
VAL: 1, 20, 300, 4000
LINE: 2
CTXT: imgs
LABEL: f(t)
VAL: a , b, bb, ccc, dddd
LINE: 3
CTXT: imgs
LABEL: g(t)
VAL: U, V, VV, WWW, XXXX
이 간단한 상황에서 다음과 같은 출력을 생성하겠습니다. nicematrix
표를 참조하세요. 그러나 이는 첫 번째 기능일 뿐입니다. 예를 들어 f
문서 뒷부분에서 최대값을 계산하고 싶습니다 . 그러기 위해서는 레이블 과 관련 값을 imgs
찾는 등 컨텍스트를 복구해야 합니다.f(t)
\documentclass[11pt, a4paper]{article}
\usepackage{nicematrix}
\begin{document}
\section{What the user types}
\begin{verbatim}
\begin{functable}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
\end{verbatim}
\section{What the user sees}
$\begin{NiceArray}[cell-space-limits = 3pt]{c*{4}{|c}}
t & 1 & 20 & 300 & 4000
\\ \hline
f(t) & a & bb & ccc & dddd
\\ \hline
g(t) & U & VV & VVV & WWW
\end{NiceArray}$
\section{What can be do after}
The user can ask for example to rebuild the 1st table
with something like this.
\begin{verbatim}
\begin{functable}[rebuild=1]
\end{functable}
\end{verbatim}
The user can also ask to calculate the maximum value
of $f(t)$ via something like \verb+\calcfunctable{max=f(t)}+.
\end{document}
나는 두 가지 가능성을 본다.
패키지를 사용하든지
starray
, 이 프로젝트가 장기적으로 유지되지 않을까 걱정됩니다.아니면 속성 목록처럼 보이는 직접 만든 솔루션을 구현해 볼 수도 있습니다.
JSON과 유사한 구조가 예상됩니다. [2024-03-09.v1]
아이디어는 각 테이블과 연관된 변수, 즉 사전별로 반복될 수 있는 변수를 갖는 것입니다. 이렇게 얻은 각 사전에 대해 우리는 다양한 유형의 값에 액세스할 수 있습니다.
[
{
'CTX' : 'xvals',
'VAL' : ['1', '20', '300', '4000'],
'LABEL': 't',
'LINE' : '1'
},
{
'CTX' : 'imgs',
'VAL' : ['a' , 'b', 'bb', 'ccc', 'dddd'],
'LABEL': 'f(t)',
'LINE' : '2'
},
{
'CTX' : 'imgs',
'VAL' : ['U', 'V', 'VV', 'WWW', 'XXXX'],
'LABEL': 'g(t)',
'LINE' : '3'
}
]
일부 추가 정보 [2024-01-17.v1]
파서는
l3
-token 목록을 제공합니다.키 값은
VAL
쉼표로 구분된 목록으로 사용되거나L3
기능별 시퀀스로 사용될 수 있습니다. 두 번째 선택이 더 나을 것입니다.값은 다양한 상황에서 사용되며 때로는 표를 인쇄하고 때로는 계산을 수행하는 데 사용됩니다. 이는 다음에서 수행되는 작업과 유사해야 합니다.이 답변.
개념 증명 단순화 [2024-03-09.v1]
\documentclass[12pt]{article}
\ExplSyntaxOn
% -- FUNCTABLE ENV. -- %
\NewDocumentEnvironment{ functable }{ b }{%
\tns_functab_functable:n { #1 }
}{}
\cs_new:Npn \tns_functab_functable:n #1 {
\tns_core_DSL_ctxt_parser:nn { functable } { #1 }
\bigskip\par
NEW ~ DATA ~ \int_use:N \g_tns_functab_id_int
\par
TODO
}
% -- DSL - L3 -- %
\tl_new:N \g_tns_functab_semicolon_tl
\tl_gset:Nn \g_tns_functab_semicolon_tl { ; }
\tl_new:N \g_tns_functab_colon_tl
\tl_gset:Nn \g_tns_functab_colon_tl { : }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\AtBeginDocument {
\tl_gset_rescan:NnV \g_tns_functab_semicolon_tl
{}
\g_tns_functab_semicolon_tl
\tl_gset_rescan:NnV \g_tns_functab_colon_tl
{}
\g_tns_functab_colon_tl
}
% :: AGNOSTIC PARSERS :: %
\int_new:N \g_tns_functab_id_int
\int_gset:Nn \g_tns_functab_id_int { 0 }
\int_new:N \l_tns_core_ctxt_nb_line_int
\seq_new:N \l_tns_core_ctxts_seq
\tl_new:N \l_tns_core_current_ctxt_tl
\cs_new:Npn \tns_core_DSL_ctxt_parser:nn #1#2 {
% The ID nb. of the env.
\int_gincr:N \g_tns_functab_id_int
% Line by line parsing.
%
% Lines are semi-colon separated.
\seq_set_split:NVn \l_tns_core_ctxts_seq
\g_tns_functab_semicolon_tl
{ #2 }
\int_zero:N \l_tns_core_ctxt_nb_line_int
\seq_map_inline:Nn \l_tns_core_ctxts_seq {
\bigskip\par
\int_incr:N \l_tns_core_ctxt_nb_line_int
Line ~ \int_use:N \l_tns_core_ctxt_nb_line_int
\par
% Get the context and its content.
\seq_set_split:Nnn \l_tmpa_seq { = } { ##1 }
\int_set:Nn \l_tmpa_int {\seq_count:N \l_tmpa_seq}
\quad
\int_case:nnF { \int_use:N \l_tmpa_int } {
{ 1 } {
LAST - CTXT: ~
(\tl_use:N \l_tns_core_current_ctxt_tl)
}
{ 2 } {
\seq_pop_left:NN \l_tmpa_seq \l_tns_core_current_ctxt_tl
NEW - CTXT: ~
(\tl_use:N \l_tns_core_current_ctxt_tl)
}
}{
ILLEGAL!
}
% Get the optional label and its content.
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
\seq_set_split:NVV \l_tmpa_seq
\g_tns_functab_colon_tl
\l_tmpa_tl
\int_set:Nn \l_tmpa_int {\seq_count:N \l_tmpa_seq}
\par\quad
\int_case:nnF { \int_use:N \l_tmpa_int } {
{ 1 } {
NO LABEL
}
{ 2 } {
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
LABEL: ~
$(\tl_use:N \l_tmpa_tl)$
}
}{
ILLEGAL!
}
\par\quad
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
VAL: ~
$(\tl_use:N \l_tmpa_tl)$
}
}
\ExplSyntaxOff
\begin{document}
\begin{functable}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
\end{document}
답변1
업데이트
코드는 환경 savefunctable
과 명령 으로 분할됩니다 \usefunctable
. 둘 다 이름을 첫 번째 인수로 사용합니다. 환경의 내용은 내부적으로 저장되며 나중에 적절한 이름을 지정하여 savefunctable
명령과 함께 사용할 수 있습니다 .\usefunctable
\documentclass[border=6pt,varwidth]{standalone}
\usepackage{nicematrix}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\ExplSyntaxOn
\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn }
\cs_generate_variant:Nn \seq_gset_from_clist:Nn { ce }
\seq_new:N \l__projetmbc_functable_seq
\seq_new:N \l__projetmbc_key_name_list_seq
\tl_new:N \l__projetmbc_coordinates_tl
\tl_new:N \l__projetmbc_key_tl
\tl_new:N \l__projetmbc_name_tl
\NewDocumentEnvironment { savefunctable } { m +b }
{
\seq_set_split:Nnn \l__projetmbc_functable_seq { ; } {#2}
\seq_map_inline:Nn \l__projetmbc_functable_seq
{
\seq_set_split:Nnn \l__projetmbc_key_name_list_seq { = } {##1}
\int_compare:nNnT { \seq_count:N \l__projetmbc_key_name_list_seq } = { 2 }
{
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_key_tl
\seq_gclear_new:c { g__projetmbc_#1_key_\l__projetmbc_key_tl _seq }
}
\seq_set_split:Nee \l__projetmbc_key_name_list_seq { \c_colon_str } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_name_tl
\seq_gput_right:cV { g__projetmbc_#1_key_\l__projetmbc_key_tl _seq } \l__projetmbc_name_tl
\seq_gclear_new:c { g__projetmbc_#1_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq }
\seq_gset_from_clist:ce { g__projetmbc_#1_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
}
}
{}
\NewDocumentCommand \usefunctable { m m }
{
\str_case:nnF {#2}
{
{ list~of~imgs }
{
\seq_use:cn { g__projetmbc_#1_key_imgs_seq } { , ~ }
}
{ maximum~of~xvals }
{
\fp_eval:n { max ( \seq_use:cn { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq } { , } ) }
}
{ NiceArray }
{
$
\begin { NiceArray }
[ cell-space-limits = 3pt ]
{ c * { \seq_count:c { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq } } { | c } }
\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 } & \seq_use:cn { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq } { & } \\ \hline
\seq_map_indexed_inline:cn { g__projetmbc_#1_key_imgs_seq }
{
##2 & \seq_use:cn { g__projetmbc_#1_key_imgs_name_##2_seq } { & }
\int_compare:nNnF {##1} = { \seq_count:c { g__projetmbc_#1_key_imgs_seq } }
{ \\ \hline }
}
\end { NiceArray }
$
}
{ plot }
{
\tl_build_begin:N \l__projetmbc_coordinates_tl
\seq_map_indexed_inline:cn { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq }
{
\tl_build_put_right:Ne \l__projetmbc_coordinates_tl
{ ( ##2 , \seq_item:cn { g__projetmbc_#1_key_imgs_name_\seq_item:cn { g__projetmbc_#1_key_imgs_seq } { 1 }_seq } {##1} ) }
}
\tl_build_end:N \l__projetmbc_coordinates_tl
\begin { tikzpicture }
\begin { axis }
[
ymin = 0
]
\addplot coordinates
{ \l__projetmbc_coordinates_tl }
;
\end { axis }
\end { tikzpicture }
}
}
{ \errmessage { wrong~option~for~functable~environment } }
}
\ExplSyntaxOff
\begin{document}
\begin{savefunctable}{example 1}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{savefunctable}
\begin{savefunctable}{example 2}
xvals = t : 1 , 2 , 3 , 4 ;
imgs = f(t) : 8 , 5 , 7 , 6 ;
\end{savefunctable}
Using \texttt{example 1} with \texttt{NiceArray}: \usefunctable{example 1}{NiceArray}
The maximum of the \texttt{xvals} of \texttt{example 2}: \usefunctable{example 2}{maximum of xvals}
The list of \texttt{imgs} of \texttt{example 1}: \usefunctable{example 1}{list of imgs}
A \texttt{plot} for \texttt{example 2}: \usefunctable{example 2}{plot}
\end{document}
원래 답변
환경이 functable
정의됩니다. 하나의 필수 인수가 필요하며 그 이후에는 본문이 필요합니다.
몸체는 먼저 ;
로 분할됩니다 \seq_set_split:Nnn
. 그런 다음 항목이 분할됩니다 =
. xvals
또는 와 같은 키는 imgs
에 저장됩니다 \l__projetmbc_key_tl
.
t
마찬가지로 또는 같은 이름은 f(t)
에 저장됩니다 \l__projetmbc_name_tl
.
환경은 functable
첫 번째 필수 인수에 따라 달라집니다. 다음은 NiceArray
, 및 maximum of xvals
에 대한 예입니다 .list of imgs
plot
\documentclass[border=6pt,varwidth]{standalone}
\usepackage{nicematrix}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\ExplSyntaxOn
\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn }
\cs_generate_variant:Nn \seq_set_from_clist:Nn { ce }
\seq_new:N \l__projetmbc_functable_seq
\seq_new:N \l__projetmbc_key_name_list_seq
\tl_new:N \l__projetmbc_coordinates_tl
\tl_new:N \l__projetmbc_key_tl
\tl_new:N \l__projetmbc_name_tl
\NewDocumentEnvironment { functable } { m +b }
{
\seq_set_split:Nnn \l__projetmbc_functable_seq { ; } {#2}
\seq_map_inline:Nn \l__projetmbc_functable_seq
{
\seq_set_split:Nnn \l__projetmbc_key_name_list_seq { = } {##1}
\int_compare:nNnT { \seq_count:N \l__projetmbc_key_name_list_seq } = { 2 }
{
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_key_tl
\seq_clear_new:c { l__projetmbc_key_\l__projetmbc_key_tl _seq }
}
\seq_set_split:Nee \l__projetmbc_key_name_list_seq { \c_colon_str } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_name_tl
\seq_put_right:cV { l__projetmbc_key_\l__projetmbc_key_tl _seq } \l__projetmbc_name_tl
\seq_clear_new:c { l__projetmbc_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq }
\seq_set_from_clist:ce { l__projetmbc_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
}
\str_case:nnF {#1}
{
{ list~of~imgs }
{
\seq_use:Nn \l__projetmbc_key_imgs_seq { , ~ }
}
{ maximum~of~xvals }
{
\fp_eval:n { max ( \seq_use:cn { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq } { , } ) }
}
{ NiceArray }
{
$
\begin { NiceArray }
[ cell-space-limits = 3pt ]
{ c * { \seq_count:c { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq } } { | c } }
\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 } & \seq_use:cn { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq } { & } \\ \hline
\seq_map_indexed_inline:Nn \l__projetmbc_key_imgs_seq
{
##2 & \seq_use:cn { l__projetmbc_key_imgs_name_##2_seq } { & }
\int_compare:nNnF {##1} = { \seq_count:N \l__projetmbc_key_imgs_seq }
{ \\ \hline }
}
\end { NiceArray }
$
}
{ plot }
{
\tl_build_begin:N \l__projetmbc_coordinates_tl
\seq_map_indexed_inline:cn { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq }
{
\tl_build_put_right:Ne \l__projetmbc_coordinates_tl
{ ( ##2 , \seq_item:cn { l__projetmbc_key_imgs_name_\seq_item:Nn \l__projetmbc_key_imgs_seq { 1 }_seq } {##1} ) }
}
\tl_build_end:N \l__projetmbc_coordinates_tl
\begin { tikzpicture }
\begin { axis }
[
ymin = 0
]
\addplot coordinates
{ \l__projetmbc_coordinates_tl }
;
\end { axis }
\end { tikzpicture }
}
}
{ \errmessage { wrong~option~for~functable~environment } }
}
{}
\ExplSyntaxOff
\begin{document}
Using \texttt{NiceArray}:
\begin{functable}{NiceArray}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
The maximum of the \texttt{xvals}:
\begin{functable}{maximum of xvals}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
The list of \texttt{imgs}:
\begin{functable}{list of imgs}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
A plot:
\begin{functable}{plot}
xvals = t : 1 , 2 , 3 , 4 ;
imgs = f(t) : 8 , 5 , 7 , 6 ;
\end{functable}
\end{document}