改ページを伴うlistingsの環境中で行番号をコピーしないようにしたい

改ページを伴うlistingsの環境中で行番号をコピーしないようにしたい

- Y O の投稿
返信数: 4

お世話になります。

listingsで載せたコードをコピーする際、行番号も選択されてしまうことが気になっており、対処法を模索していました。
今のところStack Exchangeであった最後の回答を参考にしています。
本来行番号を出力するところでは出力せず、グローバルマクロ \typesetPendingLineNumbers に追加しておき、lstlistingの終わりで作成したフックで出力します。

ここで、改ページを伴う場合においても、行番号をうまく表示させたいと考えて以下のコマンドを追記しました。

\AddToHookNext{shipout/before}{%
   \setbox\ShipoutBox=\vbox{    \box\ShipoutBox%
   \begin{tikzpicture}[remember picture, overlay]%
    \typesetPendingLineNumbers
    \end{tikzpicture}}%
   \gdef\typesetPendingLineNumbers{}% 
}

改ページするとき、今まで蓄えていた行番号を出力し、グローバルマクロ \typesetPendingLineNumbers をリセットするつもりで書きました。

しかしこの変更を加えると、次ページに表示されるべき行番号が一部分だけ前ページに表示されるようになってしまいました。この様子を以下の画像で示します。
image.pngimage%20%281%29.png
マクロ作成についてはあまり経験がなく、追記したコードに何かしら問題があるのかもしれないと考えています。

なお、私の環境はWindows PCで、TeX Live 2023を使用して以下のコマンドでビルドしています。
latexmk -pdfdvi .\main.tex

以上の現象の原因および対処方法について、ご教示いただけますと幸いです。

よろしくお願いいたします。

Y O への返信

Re: 改ページを伴うlistingsの環境中で行番号をコピーしないようにしたい

- 本田 知亮 の投稿
すごいこと考えますね。。。

TeXは少し先まで処理してそのあとページ分割するので,
ページの先頭のほうのものは
実際には前のページで組版されているという仕様が原因だと思います.

例えば,
\documentclass{article}
\begin{document}
\thepage\par%%%これを100回くらい繰り返す
\end{document}
なんてすると,2ページ目から先頭のいくつかは前のノンブルになるはずです.

これと同様にshipout/beforeに登録された
\typesetPendingLineNumbers
が1ページ目の処理で 27 行目まで実行されてしまって
(shipout/beforeの処理が始まるときに27行目の情報がpendingされているという方が正しいだろうと思います),
1ページの最初(実際は2ページ目の最初の行の行番号の位置をそのまま1ページに持ってきた場所だと思います)に27行目が現れる
といったところでしょう.そして27行目までの情報を消して2ページに入るので
28行目から行番号が現れるといったところだとおもいます

きちんとしようと思ったら
行番号をpendingする際に各ページごとにpendingすることにしてその情報を外部に保存して
ページごとにそのpending情報を使うくらいしないとうまくいかないと思います
あるページの処理の際にそこのページ番号を正確に取得するのがそもそも厄介なんですが
それは
https://okumuralab.org/tex/mod/forum/discuss.php?d=3896
でZ.R.さんご指摘のrefcountをうまく使えばすっきりするのかもしれません.

さらに複数のlistingsが存在したり,同一ページに複数のlistingがあると衝突の可能性があるので
listingsごとに一意の名前をつける必要性もあるように思います.
この一意の名前を使ってrefcountでページ番号を取得したり,
nodeの名前を付けたりすればいいような気もします.

好き勝手なアイデアだけですがご容赦を
本田 知亮 への返信

Re: 改ページを伴うlistingsの環境中で行番号をコピーしないようにしたい

- 和田 勇 の投稿

本田さんが指摘されているところに needspace 的なことが差し込めないか 考えているのですが、うまくいきません。

類似の打開策がないかと調べていたら、 { ...} をあまり使わないであろう言語であれば 【LaTeX,listings】行番号を表示したい!でも行番号ごとコピーしないで…… を参考に numberstyle=\fakeTypesetLineNumber をコメントアウトし、 backgroundcolor=\color{white} を使えば良さそうですが、 この方法でも LaTeX の場合は、{ ...}を検知すると行番号をとらえてしまいます。

Windows の実機環境が無いので下記の操作は macOS の Preview.app で検証しただけなのですが、 今回、拡張された numberstyle=\fakeTypesetLineNumber を取り除いて、 元々の listings に戻し、ご利用の windows のプレビュ用アプリで以下の操作が 実現できれば良いのですが。

その方法は「 alt + shift キーを併用してマウスポインターで必要な矩形領域を選択する」です。 欠点は、直感的ではないことかしら。また、一行が長いと選択操作の面倒な感じは否めませんね。

和田 勇 への返信

Re: 改ページを伴うlistingsの環境中で行番号をコピーしないようにしたい

- Y O の投稿
和田様
ご返信ありがとうございます。

挙げていただいたQiitaの記事に関してですが、WindowsのAcrobat Readerで試したところ、
従来手法および提案手法のどちらでも、コード選択時に行番号まで選択される問題は解決しませんでした。
一方、UbuntuのEvinceではどちらの手法でもコード部分のみを(行番号と分けて)選択可能でした。
(もしかしたら、Mac OS専用のノウハウなのかもしれないですね...)
試していただき、ありがとうございます。

「 alt + shift キーを併用してマウスポインターで必要な矩形領域を選択する」方法については、Acrobat Readerにおいて有効であることを確認しました。
他のリーダーは試していませんが、この方法によりWindowsでもコード部分だけをコピーすることが可能です。

確かにこの選択方法で問題を回避できますが、ある程度作り込んであるPDFリーダーのインストールが必要となります。
Windowsではデフォルトで高度なPDFリーダーがデフォルトでインストールされていないはずなので、
特殊な操作はせず、普通にコードを選択しただけで行番号を選択せずコピーできるように、LaTeX上で工夫できたらいいなと考えています。

貴重なご意見大変参考になりました。
ありがとうございます。
本田 知亮 への返信

Re: 改ページを伴うlistingsの環境中で行番号をコピーしないようにしたい

- Y O の投稿
本田様
ご返信ありがとうございます。
 
> TeXは少し先まで処理してそのあとページ分割するので,
> ページの先頭のほうのものは
> 実際には前のページで組版されているという仕様が原因だと思います.

なるほど、そんな仕様があったのですね。気が付きませんでした。
また、様々なアイデアありがとうございます。助かります。

知らないことが多く、すぐに実践はできませんが、少しずつ調べながら試していこうと思います。
ありがとうございます。