Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

- takada hiroyuki の投稿
返信数: 9

質問ですが,前置きが長いです.

動機

論文を書いていて,定理や補題の中で使用するenumerate環境を引用するときに,”定理 3.1 (i) より” とか”補題 2.2 (iii) により”といった言い回しが頻繁にあって,定理のラベルとリストのラベルを管理するのが大変になってきました.

リストのラベルだけを引用したら,それが属する定理環境の情報は自動で補完するというものぐさなことをやりたくなりました.

theoremやlemmaの環境を

\newtheorem{theo}{定理}
\newtheorem{lemm}{補題}

と定めたとしたときに
\newcommand{\setenvtheo}{\renewcommand{\theenumi}{定理~\thetheo~(\roman{enumi})}}

\newcommand{\setenvlemm}{\renewcommand{\theenumi}{補題~\thelemm~(\roman{enumi})}}

\newcommand{\setenvnormal}{\renewcommand{\theenumi}{(\roman{enumi})}

と環境毎にenumiに関するラベルのフォーマットを定義して,

\begin{theo}

\setenvtheo

本文記述

\end{theo}

\setenvnormal

というように毎回ラベルフォーマットを変更するということを考えたのですが,環境毎に命令を作るのは定義が長くなるので,\setenvという命令と\resetenvという命令だけを作成し,\setenvで,\setenvtheoや\setenvlemmのような効果を,\resetenvだけで\setenvnormalのような効果を得るように改造しようと考えました.つまりどの環境でenumerateを使っているのかを,そのときのtheoremカウンタとtheorem実体名("定理"とか"補題"の文字列のこと)を読みとることで自動補完にできないかと考えました.カウンタに関してはtexコードの解説が豊富にあったのでなんとかなりそうなのですが.

質問

\c@theo, \c@lemm などでカウンタの値は取り出せると思うのですが,theoの印字される名前"定理"やlemmの印字される名前"補題"はどういう変数に記憶されているのでしょうか.(\begin{theo}\end{theo} で"定理"という文字列が定理の最初に印字されているので必ずどこかに記憶されているはずだと思ったのですが...)

質問

description環境で \item[hogehoge] としたときに文字列hogehogeを取得するうまい方法はありませんか.こちらの方は文字列hogehogeがどこかでまた使われるというわけではなさそうなので,description環境を変更するかmylist環境で文字列を何かの変数に突っ込む必要があるのかもしれません...

どうぞよろしくお願いいたします.

takada hiroyuki への返信

Re: Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

- 匿 名 の投稿
# 「動機」にあるような処理を行うには,むしろ
# prettyref パッケージか何かの機能を用いたほうが
# うまくいくような気もします.それはともかく,

第 1 の質問について:
そのような「変数」はありません.
ただし,(定理型の環境をカスタマイズするような
パッケージを用いていない場合,通常は)
\@begintheorem,\@opargbegintheorem の第 1 引数が
見出し文字列になります.
したがって,\@begintheorem,\@opargbegintheorem の
定義に手を加えて,第1引数を適当な名称のマクロに
保存すればよいでしょう.

第 2 の質問について:
やはり,\@item の第 1 引数を「取得」できるように
すればよいでしょう.
ただし,第 1 の質問の場合のように
単に適当なマクロに保存すればすむ状況なのか,
それとも「相互参照」したい状況なのかは判然としません.
後者であれば,相互参照に用いる参照用のキーの与え方を
どうするのかという点から検討する必要があるでしょう.
匿 名 への返信

Re: Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

- 匿 名 の投稿
とりあえず,第 1 の質問に関しては次の例を検討してください.
enumerate 環境の番号の相互参照のみが問題なのであれば
この仮定が成り立たない場合は改めて考えることになりますが),
環境の見出し文字列などを \p@enumi に仕込むのが簡単でしょう.


%%% 例 1
\documentclass{jarticle}
\makeatletter
\def\@begintheorem#1#2{%
  \trivlist
  \protected@edef\p@enumi{#1~#2~}%
  \item[\hskip \labelsep{\bfseries #1\ #2}]}
\def\@opargbegintheorem#1#2#3{%
  \trivlist
  \protected@edef\p@enumi{#1~#2~}%
  \item[\hskip \labelsep{\bfseries #1\ #2\ (#3)}]}
\makeatother

\def\theenumi{(\roman{enumi})}
%%% 相互参照時にもパーレンをつけるので,パーレン込みでよい.
\def\labelenumi{\theenumi}

\newtheorem{thm}{定理}
\newtheorem{lem}{補題}
\begin{document}
\begin{lem}
サンプル
\begin{enumerate}
\item サンプル1\label{lem:sample:1}
\item サンプル2\label{lem:sample:2}
\end{enumerate}
\end{lem}

\begin{thm}
サンプルですよ
\begin{enumerate}
\item サンプルだってば(\ref{lem:sample:1}参照)\label{thm:sample:1}
\item サンプルだと言ってるでしょ(\ref{lem:sample:2}参照)
\end{enumerate}
\end{thm}
\ref{thm:sample:1}によれば……
\end{document}

%%% 例 2
\documentclass{jarticle}

\usepackage{prettyref}
\newrefformat{thm}{定理~\ref{#1}}
\newrefformat{lem}{補題~\ref{#1}}

\makeatletter
\def\@begintheorem#1#2{%
  \trivlist
  \protected@edef\p@enumi{#2~}%
  \item[\hskip \labelsep{\bfseries #1\ #2}]}
\def\@opargbegintheorem#1#2#3{%
  \trivlist
  \protected@edef\p@enumi{#2~}%
  \item[\hskip \labelsep{\bfseries #1\ #2\ (#3)}]}
\makeatother

\def\theenumi{(\roman{enumi})}
%%% 相互参照時にもパーレンをつけるので,パーレン込みでよい.
\def\labelenumi{\theenumi}

\newtheorem{thm}{定理}
\newtheorem{lem}{補題}
\begin{document}
\begin{lem}
サンプル
\begin{enumerate}
\item サンプル1\label{lem:sample-1}
\item サンプル2\label{lem:sample-2}
\end{enumerate}
\end{lem}

\begin{thm}\label{thm:sample-1}
サンプルですよ
\begin{enumerate}
\item サンプルだってば(\prettyref{lem:sample-1}参照)
\item サンプルだと言ってるでしょ(\prettyref{lem:sample-2}参照)
\end{enumerate}
\end{thm}
\prettyref{thm:sample-1}によれば……
\end{document}
匿 名 への返信

Re: Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

- takada hiroyuki の投稿
ソースありがとうございます.
\protected@edef\p@enumi{#2~}%
で\p@enumiに第二引数を保存している(つまり"定理 "や"補題 "という空白入りの文字列)
ということですね.
そして,
\def\theenumi{(\roman{enumi})) とすることで (i),(ii),(iii) のフォーマットにして
\def\labelenumi{\theenumi} で\labelコマンドでauxファイルに吐き出す文字列が
"定理 (i)","補題 (ii)" などのようになる.


匿 名 への返信

Re: Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

- 匿 名 の投稿
第 2 の質問について.
>後者であれば,相互参照に用いる参照用のキーの与え方を
>どうするのかという点から検討する必要があるでしょう.
なんて書きましたが,「enumerate 環境の場合と同様に」
\label が使えればよいということなら,
次のような処理が考えられるでしょう.
もっとも,定理型の環境などと組み合わせて用いた場合の
動作をどうするのかといった点によって,再定義内容を
調整する必要はあるでしょうけれども.
\documentclass{jarticle}
\makeatletter
\def\@item[#1]{%
  \if@noparitem
    \@donoparitem
  \else
    \if@inlabel
      \indent \par
    \fi
    \ifhmode
      \unskip\unskip \par
    \fi
    \if@newlist
      \if@nobreak
        \@nbitem
      \else
        \addpenalty\@beginparpenalty
        \addvspace\@topsep
        \addvspace{-\parskip}%
      \fi
    \else
      \addpenalty\@itempenalty
      \addvspace\itemsep
    \fi
    \global\@inlabeltrue
  \fi
  \everypar{%
    \@minipagefalse
    \global\@newlistfalse
    \if@inlabel
      \global\@inlabelfalse
      {\setbox\z@\lastbox
      \ifvoid\z@
        \kern-\itemindent
      \fi}%
      \box\@labels
      \penalty\z@
    \fi
    \if@nobreak
      \@nobreakfalse
      \clubpenalty \@M
    \else
      \clubpenalty \@clubpenalty
      \everypar{}%
    \fi}%
  \if@noitemarg
    \@noitemargfalse
    \if@nmbrlist
      \refstepcounter\@listctr
    \fi
  \else%%% この行と次の行を追加
    \protected@edef\@currentlabel{#1}%
  \fi
  \sbox\@tempboxa{\makelabel{#1}}%
  \global\setbox\@labels\hbox{%
    \unhbox\@labels
    \hskip \itemindent
    \hskip -\labelwidth
    \hskip -\labelsep
    \ifdim \wd\@tempboxa >\labelwidth
      \box\@tempboxa
    \else
      \hbox to\labelwidth {\unhbox\@tempboxa}%
    \fi
    \hskip \labelsep}%
  \ignorespaces}

\makeatother
\begin{document}
\begin{description}
\item[項目1] サンプル1\label{desc:item-1}
\item[項目2] サンプル2\label{desc:item-2}
\end{description}
\ref{desc:item-1}および\ref{desc:item-2}によれば,これはただのサンプル.
\end{document}
匿 名 への返信

Re: Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について

- takada hiroyuki の投稿
サンプル3についてありがとうございます.
また説明不足で大変ご迷惑をおかけいたしました.
description環境の特性を考えると定理 2.1 項目1 のような記述より
項目1だけでも良い場合と
定理2.1 仮定 [A] と補題1.1 仮定[A] というように同じ項目名を使用してしまったら,
定理環境の見出しを添えた方が良い場合とがあって,
そのどちらにも対応できるように,使用者が後でフォーマットをいじれるようにしておけば良いと考えていました.なので,今回の質問では,"定理","補題"などの文字列や
description の項目内にある文字列をどのようにして引き出せば良いか(既にそのような機能が既存パッケージにあるのか?)という質問にとどめようと考えていました.

サンプル3については読解するのに少し時間がかかってしまいそうですが,
動作としては所望したものになっていました.
takada hiroyuki への返信

サンプル3の検討結果

- takada hiroyuki の投稿

item[#1] を書き換えたことによる副作用を見つけました.

症状:

Theorem環境の見出し(ボールド体)もauxファイルに書き込まれてしまう.

原因:

\makeatletter
\def\@begintheorem#1#2{%
  \trivlist
  \item[\hskip \labelsep{\bfseries #1\ #2}]}
\def\@opargbegintheorem#1#2#3{%
  \trivlist
  \item[\hskip \labelsep{\bfseries #1\ #2\ (#3)}]}
\makeatother

各定理環境開始命令の最後の部分でitem[#1]を呼び出されているため.その時点でbfseriesが指定されている.またitem[#1]内部では,定理環境の見出しなのか,リストの見出しなのか確認することが困難.

考えられそうな対策:item[#1]へのラッパーmyitem[#1]などを別途作成して,list環境又はtheorem環境で使えるようにする.オリジナルitemに引数を食わせる前に必要な引数を後で加工できるようにどこかに保存しておく.

#TeXについて勉強不足(勉強中)です.

takada hiroyuki への返信

Re: サンプル3の検討結果

- 匿 名 の投稿
「2009年 03月 07日(土曜日) 14:48」の定義例を用いた場合の話ですか?
そうであれば,
・「description 環境内に限り」\@item をあの例のように変更する
・あの例で追加した処理を,description 環境内の場合に限り実行する
といった変更を施せばよいでしょう.

後者の方針をとれば,例えば次のようになります.
# が,「本当にやりたいこと」は質問者本人しか知らない以上,
# 質問者自身で然るべき学習を済ませておくことが望ましいでしょう.
\documentclass{jarticle}
\makeatletter
\def\@item[#1]{%
  \if@noparitem
    \@donoparitem
  \else
    \if@inlabel
      \indent \par
    \fi
    \ifhmode
      \unskip\unskip \par
    \fi
    \if@newlist
      \if@nobreak
        \@nbitem
      \else
        \addpenalty\@beginparpenalty
        \addvspace\@topsep
        \addvspace{-\parskip}%
      \fi
    \else
      \addpenalty\@itempenalty
      \addvspace\itemsep
    \fi
    \global\@inlabeltrue
  \fi
  \everypar{%
    \@minipagefalse
    \global\@newlistfalse
    \if@inlabel
      \global\@inlabelfalse
      {\setbox\z@\lastbox
      \ifvoid\z@
        \kern-\itemindent
      \fi}%
      \box\@labels
      \penalty\z@
    \fi
    \if@nobreak
      \@nobreakfalse
      \clubpenalty \@M
    \else
      \clubpenalty \@clubpenalty
      \everypar{}%
    \fi}%
  \if@noitemarg
    \@noitemargfalse
    \if@nmbrlist
      \refstepcounter\@listctr
    \fi
  \else
    \def\@tempa{description}%
    \ifx\@currenvir\@tempa
      \protected@edef\@currentlabel{#1}%
    \fi
  \fi
  \sbox\@tempboxa{\makelabel{#1}}%
  \global\setbox\@labels\hbox{%
    \unhbox\@labels
    \hskip \itemindent
    \hskip -\labelwidth
    \hskip -\labelsep
    \ifdim \wd\@tempboxa >\labelwidth
      \box\@tempboxa
    \else
      \hbox to\labelwidth {\unhbox\@tempboxa}%
    \fi
    \hskip \labelsep}%
  \ignorespaces}
\makeatother

\newtheorem{thm}{Theorem}

\begin{document}
\begin{description}
\item[項目1] サンプル1\label{desc:item-1}
\item[項目2] サンプル2\label{desc:item-2}
\end{description}
\ref{desc:item-1}および\ref{desc:item-2}によれば,これはただのサンプル.

\begin{thm}\label{thm:sample}
サンプルです.
\end{thm}
\end{document}
匿 名 への返信

Re: サンプル3の検討結果

- takada hiroyuki の投稿

いつもお世話になっております.

ご指摘の通り,「2009年 03月 07日(土曜日) 14:48」の例を用いた場合についてのコメントでした.

\@currentenvirという変数があるのですね...知りませんでした.それならば,\@item[#1]の中で環境を特定して処理を判別できますね.

貴重な情報をいただきました.ありがとうございました.

匿 名 への返信

Re: Theorem環境の接頭文字列"定理", description等の見出し文字列の取得について(状況説明)

- takada hiroyuki の投稿
># prettyref パッケージか何かの機能を用いたほうが
これについては,パッケージを調べてみます.
パッケージで,\@begintheoremなどの第一引数が既に取り出せる状態であれば,第1の質問は解消できると思います.ありがとうございます.

>第 1 の質問について:
>そのような「変数」はありません.
情報ありがとうございます.

>第 2 の質問について:
>やはり,\@item の第 1 引数を「取得」できるように
>すればよいでしょう.
ありがとうございます.そのようにします.

>ただし,第 1 の質問の場合のように
>単に適当なマクロに保存すればすむ状況なのか,
>それとも「相互参照」したい状況なのかは判然としません.
目的は相互参照です.

数式の参照の場合 (1) のフォーマットと(3.1)のフォーマットをよく使用しますが,
後者のフォーマットが\renewcommandだけで変更できるのは
\thesectionが保存されていることと,ピリオドが環境に依存しない文字だからでした.
なので,theorem, lemma などの文字列も\renewcommandで操作可能な形でどこかに保存されているならばそれを使えば良いなと思いました.

>後者であれば,相互参照に用いる参照用のキーの与え方を
>どうするのかという点から検討する必要があるでしょう.

参照用のキーとは
\begin{theorem}\label{theo:main}
Let us assume that
\begin{description}
\item[{[A]}] \label{assu:A} $f$ is additive, i.e. $f(s,t)=f(s,u)+f(u,t)$ for all $u$,
\item[{[C]}] \label{assu:C} $f$ is continous, i.e. $f(s\pm,t)=f(s,t\pm)=f(s,t)$,
\item[{[I]}] \label{assu:I} $f$ is wide-sense increasing, i.e. $f(s,t_1)\le f(s,t_2)$ if $t_1\le t_2$.
\end{description}
Then we have hogehogehoge.
\end{theorem}
のうちのassu:A,assu:C,assu:I などのことでしょうか.