암호화폐에서 증명에는 일련의 게임이 포함됩니다. 각 게임에는 라인 목록이 포함되어 있습니다. 인접한 게임은 라인 수가 적은 것(보통 1개)을 제외하면 거의 동일합니다. 나는 이전 게임을 다음 게임에 복사하고 새 게임을 수정하곤 했습니다. 하지만 이는 정말 불편하고 유지 관리도 어렵습니다. 결과 소스 파일도 불필요하게 큽니다. 20개의 게임이 있고 각각 10개의 줄이 있는 증명을 생각해 보세요.
그래서 저는 이를 위한 환경을 만들기로 결정했습니다. 이는 각 항목이 "열거" 환경이기도 한 "열거" 환경처럼 보입니다. 외부 열거자를 위한 새 항목(게임)을 생성할 때마다 변경하려는 마지막 게임의 라인을 가변 매개변수로 지정합니다. 매개변수에 지정되지 않은 마지막 게임의 모든 라인을 환경 자체에서 자동으로 복사하고 싶습니다.
이것이 어떻게 달성될 수 있는지 아시나요?
답변1
그것과의 작은 싸움 후에(처음 사용 prop
) 나는 이것이 작동한다고 생각합니다. 비록 그것이 약간 혼합되어 있지만 더 나은 "사용자 인터페이스"를 생각하는 것이 더 나을 것입니다.
첫째, 인수가 있는 예외와 cryptolist
유사한 환경이 있습니다 . 선택적 인수가 있습니다.enumerate
\item{…}
cryptolist
목록의 이름(기본적으로 default
) 이는 동시에 여러 다른 목록을 관리할 수 있는 옵션을 제공합니다.
\replacecryptoitems
그런 다음 두 개의 명령 (선택적 인수의 이름과 대체할 항목의 일반적인 키-값 목록)과 \printcryptolist
(선택적 인수의 이름)이 있습니다 . 예를 들어 인쇄할 수 \replacecryptoitems{2=Modified second item, 3=modified third item}
있습니다 \printcryptolist
.
새로운 암호화폐 목록을 초기화하려면 \newcryptolist{name}
.
\documentclass{scrartcl}
\usepackage{xparse,enumitem}
\ExplSyntaxOn
\NewDocumentCommand \newcryptolist { m }
{
\prop_new:c { g_cryptolist_#1_prop }
\int_new:c { g_cryptolist_#1_int }
}
\NewDocumentEnvironment { cryptolist } { O{default} }
{
\tl_set:Nn \l_cryptolist_name_tl { #1 }
\int_gzero:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
\prop_gclear:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
\enumerate
\cs_set_eq:NN \normalitem \item
\cs_set_eq:NN \item \cryptoitem
}
{ \endenumerate }
\NewDocumentCommand \cryptoitem { o m }
{
\int_gincr:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
\tl_set:Nx \l_cryptolist_item_tl
{ \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
\prop_gput:con { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
{ \l_cryptolist_item_tl }
{ #2 }
\IfValueTF { #1 } { \normalitem [ #1 ] } { \normalitem }
#2
}
\NewDocumentCommand \printcryptolist { O{default} }
{ \cc_printitems:n { #1 } }
\NewDocumentCommand \replacecryptoitems { O{default} m }
{ \cc_replaceitems:nn { #1 } { #2 } }
\tl_new:N \l_cryptolist_name_tl
\tl_new:N \l_cryptolist_item_tl
\prop_new:N \g_cryptolist_default_prop
\int_new:N \g_cryptolist_default_int
\keys_define:nn { cryptolist }
{
unknown .code:n =
\prop_gput:cVn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
\l_keys_key_tl { #1 }
}
\cs_new_protected:Npn \cc_printitems:n #1
{
\begin{enumerate}
\tl_set:Nn \l_cryptolist_name_tl { #1 }
\int_step_inline:nnnn { 1 } { 1 }
{ \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
{
\item
\prop_item:cn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
{ ##1 }
}
\end{enumerate}
}
\cs_new_protected:Npn \cc_replaceitems:nn #1 #2
{
\tl_set:Nn \l_cryptolist_name_tl { #1 }
\keys_set:nn { cryptolist } { #2 }
}
\ExplSyntaxOff
\newcryptolist{anotherlist}
\begin{document}
\begin{cryptolist}[anotherlist]
\item{First item to be used later;}
\item{second item.}
\end{cryptolist}
\begin{cryptolist}
\item{First item}
\item{Second item}
\item{Third item}
\item{Last item}
\end{cryptolist}
\replacecryptoitems{2 = Second (modified) item, 4 = Last modified item.}
\printcryptolist
\replacecryptoitems[anotherlist]{1=Changing the first one to be used now;}
\printcryptolist[anotherlist]
\end{document}
새로운 요청을 돕기 위한 확장 코드입니다. 이 경우 \replacecryptoitems
대체된 항목을 사용할 때마다 기록됩니다. 그리고 다음 시간이 \printcryptoitems
주어졌습니다 (오직다음에 한 번 사용하면 재설정됩니다) 변경된 항목이 \gamediff{…}
편집됩니다.
\documentclass{scrartcl}
\usepackage{xparse,enumitem}
\usepackage[x11names]{xcolor}
\ExplSyntaxOn
\NewDocumentCommand \gamediff { m }
{ \textcolor { Tomato3 } { #1 } }
\NewDocumentCommand \newcryptolist { m }
{
\prop_new:c { g_cryptolist_#1_prop }
\int_new:c { g_cryptolist_#1_int }
\seq_new:c { g_cryptolist_modifieditems_#1_seq }
}
\NewDocumentEnvironment { cryptolist } { O{default} }
{
\tl_set:Nn \l_cryptolist_name_tl { #1 }
\int_gzero:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
\prop_gclear:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
\enumerate[noitemsep]
\cs_set_eq:NN \normalitem \item
\cs_set_eq:NN \item \cryptoitem
}
{ \endenumerate }
\NewDocumentCommand \cryptoitem { o m }
{
\int_gincr:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
\tl_set:Nx \l_cryptolist_item_tl
{ \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
\prop_gput:con { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
{ \l_cryptolist_item_tl }
{ #2 }
\IfValueTF { #1 } { \normalitem [ #1 ] } { \normalitem }
#2
}
\NewDocumentCommand \printcryptolist { O{default} }
{ \cc_printitems:n { #1 } }
\NewDocumentCommand \replacecryptoitems { O{default} m }
{ \cc_replaceitems:nn { #1 } { #2 } }
\tl_new:N \l_cryptolist_name_tl
\tl_new:N \l_cryptolist_item_tl
\prop_new:N \g_cryptolist_default_prop
\seq_new:N \g_cryptolist_modifieditems_default_seq
\int_new:N \g_cryptolist_default_int
\keys_define:nn { cryptolist }
{
unknown .code:n =
\seq_gput_right:cV
{ g_cryptolist_modifieditems_ \tl_use:N \l_cryptolist_name_tl _seq }
\l_keys_key_tl
\prop_gput:cVn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
\l_keys_key_tl { #1 }
}
\cs_new_protected:Npn \cc_printitems:n #1
{
\begin{enumerate}[noitemsep]
\tl_set:Nn \l_cryptolist_name_tl { #1 }
\int_step_inline:nnnn { 1 } { 1 }
{ \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
{
\item
\group_begin:
\seq_if_in:cnF
{ g_cryptolist_modifieditems_ \tl_use:N \l_cryptolist_name_tl _seq }
{ ##1 }
{ \cs_set_eq:NN \gamediff \prg_do_nothing: }
{
\prop_item:cn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
{ ##1 }
}
\group_end:
}
\end{enumerate}
\seq_gclear:c
{ g_cryptolist_modifieditems_ \tl_use:N \l_cryptolist_name_tl _seq }
}
\cs_new_protected:Npn \cc_replaceitems:nn #1 #2
{
\tl_set:Nn \l_cryptolist_name_tl { #1 }
\keys_set:nn { cryptolist } { #2 }
}
\ExplSyntaxOff
\newcryptolist{anotherlist}
\begin{document}
\begin{cryptolist}
\item{First item}
\item{Second item}
\item{Third item}
\item{Last item}
\end{cryptolist}
\replacecryptoitems{2 = Second \gamediff{(modified)} item, 4 = Last modified \gamediff{item}.}
\printcryptolist
And this next time they are not highlighted.
\printcryptolist
\end{document}
답변2
\documentclass{article}
\usepackage{color}
\usepackage{expl3}
\newcommand\gamediff[2][red]{\color{#1}{\underline{\color{black}{#2}}}\color{black}{}}
\newsavebox\MBox
\newcommand\gamediffeq[2][red]{{\sbox\MBox{$#2$}\rlap{\usebox\MBox}\color{#1}\rule[-1.2\dp\MBox]{\wd\MBox}{0.5pt}}}
\ExplSyntaxOn
\seq_new:N \g_crypto__gameseq_seq
\tl_new:N \g_crypto__gameseq_tl
\int_new:N \g_crypto__gameseq_i
\cs_new:Npn \crypto__gameseq_move:ccn #1#2#3
{
\int_step_inline:nnnn { 1 } { 1 } { #3 }
{
\seq_gpop_left:cN { #1 } \g_crypto__gameseq_tl
\seq_gput_left:cV { #2 } \g_crypto__gameseq_tl
}
}
\cs_new:Npn \crypto__gameseq_store:cn #1#2
{
\crypto__gameseq_move:ccn { #1 } { g_crypto__gameseq_seq } { #2 }
}
\cs_new:Npn \crypto__gameseq_load:cn #1#2
{
\crypto__gameseq_move:ccn { g_crypto__gameseq_seq } { #1 } { #2 }
}
\cs_new:Npn \crypto__gameseq_out:N #1
{
\item \tl_use:N #1
}
\cs_new:Npn \crypto_gameseq_new:c #1
{
\seq_gclear_new:c { g_crypto_gameseq_#1 }
\int_gzero_new:c { g_crypto_gameseq_#1_num }
}
\cs_new:Npn \crypto_gameseq_add:cnn #1#2#3
{
\crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
\seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
}
\cs_new:Npn \crypto_gameseq_del:cnn #1#2#3
{
\crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
}
\cs_new:Npn \crypto_gameseq_mod:cnn #1#2#3
{
\crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
}
\cs_new:Npn \crypto_gameseq_get:c #1
{
\int_gincr:c { g_crypto_gameseq_#1_num }
\item[Game~\int_use:c { g_crypto_gameseq_#1_num }.]
\begin{enumerate}
\seq_map_function:cN { g_crypto_gameseq_#1 } \crypto__gameseq_out:N
\end{enumerate}
}
\cs_new_eq:NN \seqnew \crypto_gameseq_new:c
\cs_new_eq:NN \seqout \crypto_gameseq_get:c
\cs_new_eq:NN \seqadd \crypto_gameseq_add:cnn
\cs_new_eq:NN \seqdel \crypto_gameseq_del:cnn
\cs_new_eq:NN \seqmod \crypto_gameseq_mod:cnn
\ExplSyntaxOff
\begin{document}
\begin{itemize}
\seqnew{cc}
\seqadd{cc}{1}{first item}
\seqadd{cc}{2}{third item}
\seqadd{cc}{2}{fourth item}
\seqout{cc}
\seqmod{cc}{2}{\gamediff{second} item}
\seqout{cc}
\seqout{cc}
\end{itemize}
\end{document}
첫 번째 문제를 해결하기 seq
위해 prop
. 그리고 그 결과는
하지만 두 번째 문제를 어떻게 해결할 수 있을지 알 수 없었습니다. 나는 두 가지 아이디어를 가지고 있습니다 :
게임이 인쇄될 때마다 모든 항목을 살펴보고 에 대한 모든 호출을 제거합니다
gamediff
. 장애물이gamediff
최상위 수준에 있지 않을 수도 있습니다.{{gamediff}}
또는 일 수 있습니다$gamediff$
.목록에 항목을 저장할 때 사용자는 직접 호출하지 않고 현재 게임이 어디에 있는지
gamediff
생성하는 함수를 호출합니다 . 그리고 게임이 인쇄되면 평가되며 첫 번째 매개변수가 현재 게임과 동일한 항목만 해당 콘텐츠를 강조 표시합니다.gamediff[i]
i
gamediff
Manuel의 아이디어로 문제 2도 처리됩니다.
\documentclass{article}
\usepackage{color}
\usepackage{expl3}
\newcommand\highlight[2][red]{\color{#1}{\underline{\color{black}{#2}}}\color{black}{}}
\newsavebox\MBox
\newcommand\highlighteq[2][red]{{\sbox\MBox{$#2$}\rlap{\usebox\MBox}\color{#1}\rule[-1.2\dp\MBox]{\wd\MBox}{0.5pt}}}
\ExplSyntaxOn
\seq_new:N \g_crypto__gameseq_seq
\tl_new:N \g_crypto__gameseq_tl
\int_new:N \g_crypto__gameseq_i
\cs_new:Npn \crypto__gameseq_move:ccn #1#2#3
{
\int_step_inline:nnnn { 1 } { 1 } { \int_eval:n { \int_eval:n { #3 } * 2 } }
{
\seq_gpop_left:cN { #1 } \g_crypto__gameseq_tl
\seq_gput_left:cV { #2 } \g_crypto__gameseq_tl
}
}
\cs_new:Npn \crypto__gameseq_store:cn #1#2
{
\crypto__gameseq_move:ccn { #1 } { g_crypto__gameseq_seq } { #2 }
}
\cs_new:Npn \crypto__gameseq_load:cn #1#2
{
\crypto__gameseq_move:ccn { g_crypto__gameseq_seq } { #1 } { #2 }
}
\cs_new:Npn \crypto_gameseq_new:c #1
{
\seq_gclear_new:c { g_crypto_gameseq_#1 }
\int_gzero_new:c { g_crypto_gameseq_#1_num }
}
\cs_new:Npn \crypto_gameseq_add:cnn #1#2#3
{
\crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { #2 - 1 }
\seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
\seq_gput_left:cn { g_crypto_gameseq_#1 } { 1 }
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { #2 - 1 }
}
\cs_new:Npn \crypto_gameseq_del:cnn #1#2
{
\crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { #2 - 1 }
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { #2 - 1 }
}
\cs_new:Npn \crypto_gameseq_mod:cnn #1#2#3
{
\crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { #2 - 1 }
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
\seq_gput_left:cn { g_crypto_gameseq_#1 } { 1 }
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { #2 - 1 }
}
\cs_new:Npn \crypto_gameseq_get:c #1
{
\int_gincr:c { g_crypto_gameseq_#1_num }
\item[Game~\int_use:c { g_crypto_gameseq_#1_num }.]
\begin{enumerate}
\int_step_variable:nnnNn { 1 } { 1 } { \seq_count:c { g_crypto_gameseq_#1 } } \g_crypto__gameseq_i
{
\seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
\int_if_odd:nTF \g_crypto__gameseq_i
{
\tl_if_empty:NTF { \g_crypto__gameseq_tl }
{
\cs_set_eq:NN \gamediff \prg_do_nothing:
\cs_set_eq:NN \gamediffeq \prg_do_nothing:
}
{
\cs_set_eq:NN \gamediff \highlight
\cs_set_eq:NN \gamediffeq \highlighteq
}
\seq_gput_left:Nn \g_crypto__gameseq_seq {}
}
{
\item \tl_use:N \g_crypto__gameseq_tl
\seq_gput_left:cV { g_crypto__gameseq_seq } \g_crypto__gameseq_tl
}
}
\crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { \seq_count:c { g_crypto__gameseq_seq } / 2 } }
\end{enumerate}
}
\cs_new_eq:NN \seqnew \crypto_gameseq_new:c
\cs_new_eq:NN \seqout \crypto_gameseq_get:c
\cs_new_eq:NN \seqadd \crypto_gameseq_add:cnn
\cs_new_eq:NN \seqdel \crypto_gameseq_del:cnn
\cs_new_eq:NN \seqmod \crypto_gameseq_mod:cnn
\cs_new_eq:NN \gamediff \highlight
\cs_new_eq:NN \gamediffeq \highlighteq
\ExplSyntaxOff
\begin{document}
\begin{itemize}
\seqnew{cc}
\seqadd{cc}{1}{first item}
\seqout{cc}
\seqadd{cc}{2}{\gamediff{third} item}
\seqout{cc}
\seqadd{cc}{2}{fourth item}
\seqout{cc}
\seqmod{cc}{2}{\gamediff{second} item}
\seqout{cc}
\seqout{cc}
\seqdel{cc}{2}
\seqout{cc}
\end{itemize}
\end{document}
결과는