OSDN Git Service

Releases 20240514.0
[luatex-ja/luatexja.git] / src / patches / lltjp-listings.sty
1 %
2 % lltjp-listings.sty 2022-05-22
3 %
4
5 \NeedsTeXFormat{LaTeX2e}
6 \RequirePackage{etoolbox,listings,luatexbase-cctb}
7
8 \newcount\ltj@lst@japanese@min \ltj@lst@japanese@min=128
9 %%%%%%%%%%%%%%%% Japanese support
10 %% whether letter-space in a fixed mode box is doubled or not
11 \newif\if@ltj@lst@double
12 \lst@Key{doubleletterspace}f[t]{\lstKV@SetIf{#1}\if@ltj@lst@double}
13
14 %% IVS support
15 \newif\if@ltj@lst@vsraw
16 \def\ltj@lst@vscmd{}
17 \lst@Key{vsraw}f[t]{\lstKV@SetIf{#1}\if@ltj@lst@vsraw}
18 \lst@Key{vscmd}\relax{\def\ltj@lst@vscmd{#1}}
19
20 % 既定の IVS 出力コマンド
21 \def\ltjlistingsvsstdcmd#1{\@tempdima=\f@size pt%
22   \smash{\raisebox{.35\@tempdima}{\tt%
23     \fboxsep=.1\@tempdima\fbox{\fontsize{.5\@tempdima}{\z@}\selectfont
24       \oalign{\hss VS\hss\crcr\hss#1\hss\crcr}}}}}
25 \def\ltj@lst@vscmd{\ltjlistingsvsstdcmd}
26
27 % override \lst@FillFixed@
28 % \ltj@hst@hss is \ltj@lst@hss@ivs or \ltj@lst@hss@normal,
29 % according to vsraw = true or not.
30 \def\lst@FillFixed#1{{\null#1\null}\lst@FillFixed@}
31 \def\lst@FillFixed@#1{%
32   \ifx\@empty#1\else\ltj@lst@hss{\null#1\null}\expandafter\lst@FillFixed@\fi}
33 \let\lst@FillOutputBox\lst@FillFixed
34 % [space/full]flexiblemode (not much useful...)
35 \def\ltj@lst@FillFlex#1\@empty{\null#1\null}
36 \patchcmd\lst@column@flexible
37   {\let\lst@FillOutputBox\@empty}{\let\lst@FillOutputBox\ltj@lst@FillFlex}{}{}
38 \patchcmd\lst@column@fullflexible
39   {\let\lst@FillOutputBox\@empty}{\let\lst@FillOutputBox\ltj@lst@FillFlex}{}{}
40 \patchcmd\lst@column@spaceflexible
41   {\let\lst@FillOutputBox\@empty}{\let\lst@FillOutputBox\ltj@lst@FillFlex}{}{}
42
43
44 \directlua{
45   local cat_str = luatexbase.catcodetables['string']
46   local cat_lp  = luatexbase.catcodetables['latex-package']
47   local ubyte = utf.byte
48   local spccmd = string.char(0x5C) .. 'ltj@lst@hss@normal'
49   luatexja.listings = {}
50   function luatexja.listings.althss(t)
51     t = ubyte(t)
52     if not (t>=0xE0100 and t<0xE01F0) then
53       tex.sprint(cat_lp, spccmd)
54     end
55   end
56 }
57 \def\ltj@lst@hss@ivs#1{%
58   \directlua{luatexja.listings.althss('\luatexluaescapestring{#1}')}#1%
59 }
60 \def\ltj@lst@hss@double{\lst@hss\lst@hss}
61
62 % lowest level
63 \newif\if@ltj@lst@kanji
64 \lst@AddToHook{InitVars}{\@ltj@lst@kanjifalse}
65
66 \def\lst@AppendLetter{%
67     \ltj@lst@setletterflag\lst@Append}
68 \def\lst@AppendOther{%
69     \lst@ifletter\lst@Output\lst@letterfalse\fi\@ltj@lst@kanjifalse
70     \futurelet\lst@lastother\lst@Append}
71
72 \def\ltj@lst@setletterflag{%
73   \lst@ifletter
74     \if@ltj@lst@kanji\lst@Output\@ltj@lst@kanjifalse\fi
75   \else
76     \lst@lettertrue\if@ltj@lst@kanji\@ltj@lst@kanjifalse\else\lst@OutputOther\fi
77   \fi}
78
79 \def\ltj@lst@setkanjiflag{%
80   \lst@ifletter
81     \lst@Output
82   \else
83     \if@ltj@lst@kanji\else\lst@OutputOther\fi\lst@lettertrue
84   \fi\@ltj@lst@kanjitrue}
85
86 \def\ltj@lst@setopenflag{%
87   \lst@ifletter
88     \lst@letterfalse\lst@Output
89   \else
90     \if@ltj@lst@kanji\else\lst@OutputOther\fi
91   \fi\@ltj@lst@kanjitrue}
92
93 \def\ltj@lst@setcloseflag{%
94   \lst@ifletter\else\lst@lettertrue\fi\@ltj@lst@kanjitrue}
95
96 % Processing Japanese characters
97 \def\ltj@lst@ProcessJALetter#1{%
98   \lst@whitespacefalse
99   \ifnum\ltjgetparameter{jacharrange}{\ltjgetparameter{chartorange}{`#1}}=0
100     \ifnum\ltjgetparameter{postbreakpenalty}{`#1}>0
101       \ltj@lst@setopenflag    % 開き括弧類
102     \else
103       \ifnum\ltjgetparameter{prebreakpenalty}{`#1}>0
104         \ltj@lst@setcloseflag % 閉じ括弧類,句読点
105       \else
106         \ltj@lst@setkanjiflag % 通常の和文文字
107     \fi\fi
108     \advance\lst@length\@ne   % 和文文字は通常の2倍の幅
109   \else
110     \ltj@lst@setletterflag
111   \fi
112   \lst@Append#1%
113 }
114
115 % 半角カナ処理命令
116 \def\ltj@lst@ProcessJALetterHalf#1{%
117   \lst@whitespacefalse
118   \ifnum\ltjgetparameter{jacharrange}{\ltjgetparameter{chartorange}{`#1}}=0
119     \ifnum\ltjgetparameter{postbreakpenalty}{`#1}>0
120       \ltj@lst@setopenflag    % 開き括弧類
121     \else
122       \ifnum\ltjgetparameter{prebreakpenalty}{`#1}>0
123         \ltj@lst@setcloseflag % 閉じ括弧類
124       \else
125         \ltj@lst@setkanjiflag % 通常の和文文字
126     \fi\fi
127     % 半角カナは欧文文字と同じ幅
128   \else
129     \ltj@lst@setletterflag
130   \fi
131   \lst@Append#1}
132
133 % 漢字用異体字セレクタ命令
134 \def\ltj@lst@ProcessIVS#1{%
135   \lst@whitespacefalse
136   \if@ltj@lst@vsraw
137     \lst@Append#1\advance\lst@length\m@ne
138   \else
139     \lst@TrackNewLines\lst@OutputLostSpace \lst@PrintToken
140     \setbox\@tempboxa\hbox to 2\lst@width{\hss
141        \expandafter\expandafter\expandafter\ltj@lst@vscmd
142        \expandafter{\the\numexpr`#1-"E00EF\relax}%"
143     \hss}%
144     \lst@CalcLostSpaceAndOutput\lst@whitespacefalse
145   \fi
146 }
147
148 % Variation Selector
149 \def\ltj@lst@ProcessVS#1{%
150   \lst@whitespacefalse
151   \if@ltj@lst@vsraw
152     \lst@Append#1\advance\lst@length\m@ne
153   \else
154     \lst@TrackNewLines\lst@OutputLostSpace \lst@PrintToken
155     \setbox\@tempboxa\hbox to 2\lst@width{\hss
156        \expandafter\expandafter\expandafter\ltj@lst@vscmd
157        \expandafter{\the\numexpr`#1-"FDFF\relax}%"
158     \hss}%
159     \lst@CalcLostSpaceAndOutput\lst@whitespacefalse
160   \fi
161 }
162
163
164 % 半角カナ,異体字セレクタはアクティブ化
165 \def\ltj@@listing@jpsetN#1#2#3{% for (not large) range
166   \@tempcnta=\numexpr#1-1\relax\@tempcntb=\numexpr 1+#2\relax
167   \loop \global\advance\@tempcnta\@ne\ifnum\@tempcnta<\@tempcntb\relax
168     \ltj@@listing@jpsetN@{\@tempcnta}{#3}\repeat
169 }
170
171 \def\ltj@@listing@jpsetN@#1#2{{%
172     \@tempcnta=#1 \lccode`\~=\@tempcnta \lccode`\/=\@tempcnta
173     \lowercase{\gdef\@temp{\gdef~{#2/}}}}%
174   \@temptokena\expandafter\expandafter\expandafter\expandafter%
175   \expandafter\expandafter\expandafter{\expandafter\expandafter%
176   \expandafter\the\expandafter\@temptokena\@temp}%
177 }
178 \@temptokena{}
179 \ltj@@listing@jpsetN{65377}{65439}{\ltj@lst@ProcessJALetterHalf}
180 \ltj@@listing@jpsetN{65024}{65039}{\ltj@lst@ProcessVS}
181 \ltj@@listing@jpsetN{917760}{917999}{\ltj@lst@ProcessIVS}
182 \xdef\ltj@@listing@jpcmd{\the\@temptokena}\@temptokena{}
183
184 % catcode 対策
185 \newluatexcatcodetable\CatcodeTableLTJlistings
186 \setluatexcatcodetable\CatcodeTableLTJlistings{%
187   \luatexcatcodetable\CatcodeTableLaTeXAtLetter
188   \catcode\ltjlineendcomment=13%"
189   \SetCatcodeRange{"FF61}{"FF9F}{13}%     半角カナ
190   \SetCatcodeRange{"E0100}{"E01EF}{13}%   漢字用異体字セレクタ
191   \SetCatcodeRange{"FE00}{"FE0F}{13}%     Variation Selector
192 }
193
194 % redefine \lstinline and its inner commands to support Japanese characters
195 \renewcommand\lstinline[1][]{%
196     \leavevmode\bgroup % \hbox\bgroup --> \bgroup
197       \def\lst@boxpos{b}%
198       \lsthk@PreSet\lstset{flexiblecolumns,#1}%
199       \lsthk@TextStyle
200       \@ifnextchar\bgroup \ltj@lst@InlineG \ltj@lstinline@}
201 \def\ltj@lst@InlineG{%
202   \lst@Init\relax\edef\ltj@lst@temp{\the\catcode`\}}\catcode`\}=2 \catcode`\ =12\relax
203   \let\lst@arg\@empty\afterassignment\ltj@lst@InlineG@@\@temptokena}
204 \def\ltj@lst@InlineG@@{%
205   \catcode`\}=\ltj@lst@temp%
206   \expandafter\expandafter\expandafter\lst@InsideConvert%
207   \expandafter{\the\@temptokena}\lst@arg\lst@DeInit\egroup}
208 \def\ltj@lstinline@#1{%
209   \edef\ltj@lst@temp{\the\catcode`#1}
210   \lst@Init\relax\catcode`#1\ltj@lst@temp
211   \ifnum\ltj@lst@temp=\active
212     \begingroup\lccode`\~=`#1\relax
213     \lowercase{\xdef\lst@next{\noexpand\lst@InlineJ\noexpand~}}\endgroup%
214   \else
215     \edef\lst@next{\noexpand\lst@InlineJ\scantextokens{#1}}%
216   \fi\lst@next
217 }
218
219 % We redefine \lst@BeginDropInput, since now we have
220 % two additional `process macros'.
221 \def\lst@BeginDropInput#1{%
222     \lst@EnterMode{#1}%
223     {\lst@modetrue
224      \let\lst@OutputBox\@gobble
225      \let\lst@ifdropinput\iftrue
226      \let\lst@ProcessLetter\@gobble
227      \let\lst@ProcessDigit\@gobble
228      \let\lst@ProcessOther\@gobble
229      \let\lst@ProcessSpace\@empty
230      \let\lst@ProcessTabulator\@empty
231      \let\lst@ProcessFormFeed\@empty
232      \let\ltj@lst@ProcessJALetter\@gobble     % added
233      \let\ltj@lst@ProcessJALetterHalf\@gobble % added
234 }}
235
236 \directlua{
237   local utfchar, getcount = utf.char, tex.getcount
238   luatexja.listings.insert_cb = function()
239     if not luatexja.listings.patched then
240       luatexja.listings.patched = 1
241       luatexbase.add_to_callback('process_input_buffer',
242          function(buf)
243            local ret = ''
244            for i = 1, utf.len(buf) do
245               local c = utf.sub(buf, i, i)
246               local cu = utf.byte(c)
247               if cu >= \the\ltj@lst@japanese@min\space and tex.getcatcode(cu) \string~= 13 then
248                 ret = ret .. utfchar(getcount('ltjlineendcomment'))
249               end
250               ret = ret .. c
251             end
252             return ret
253           end, 'ltj.listings_unicode', 1)
254     end
255   end
256   luatexja.listings.remove_cb = function()
257     if luatexja.listings.patched then
258       luatexja.listings.patched = nil
259       luatexbase.remove_from_callback('process_input_buffer', 
260         'ltj.listings_unicode')%
261     end
262   end}
263
264 % hook!
265 \lst@AddToHook{Init}{%
266   \luatexcatcodetable\CatcodeTableLTJlistings\ltj@@listing@jpcmd
267   \lccode`\~=\ltjlineendcomment\lowercase{\def~{\ltj@lst@ProcessJALetter}}%"
268   \directlua{luatexja.listings.insert_cb()}%
269   \if@ltj@lst@double
270     \let\ltj@lst@hss@normal=\ltj@lst@hss@double
271   \else
272     \let\ltj@lst@hss@normal=\lst@hss
273   \fi
274   \if@ltj@lst@vsraw
275     \let\ltj@lst@hss=\ltj@lst@hss@ivs
276   \else
277     \let\ltj@lst@hss=\ltj@lst@hss@normal
278   \fi
279 }
280
281 \def\ltj@lst@MakeActive#1{%
282     \let\lst@temp\@empty \ltj@lst@MakeActive@#1\relax}
283 \begingroup
284 \catcode`\^^A=12
285 \catcode`\^^@=\active
286 \lccode`\$=\ltjlineendcomment \catcode`\$=13 %"
287 \lowercase{%
288 \gdef\ltj@lst@MakeActive@#1{\let\lst@next\relax%
289     \ifx#1\relax
290     \else\let\lst@next\ltj@lst@MakeActive@
291     \ifnum`#1>\numexpr\ltj@lst@japanese@min-1
292       \lccode`\^^A=`#1 
293       \lowercase{\lst@lAddTo\lst@temp{$^^A}}%$
294     \else
295       \lccode`\^^@=`#1 
296       \lowercase{\lst@lAddTo\lst@temp{^^@}}%
297     \fi\fi\lst@next}}
298 \endgroup
299
300
301 \begingroup \lccode`\~=`\ \relax \lowercase{%
302 \gdef\lst@InsideConvert@#1 #2{%
303     \ltj@lst@MakeActive{#1}%
304     \ifx\@empty#2%
305         \lst@lExtend\lst@arg{\lst@temp}%
306     \else
307         \lst@lExtend\lst@arg{\lst@temp~}%
308         \expandafter\lst@InsideConvert@
309     \fi#2}
310 }\endgroup
311
312 \lst@AddToHook{ExitVars}{%
313   \directlua{luatexja.listings.remove_cb()}%
314 }
315
316 % 白線対策
317 \newif\ifltj@lst@frame@top
318 \newdimen\ltj@lst@frame@lslimit
319 \gdef\lst@frameInit{%
320     \ltj@lst@frame@toptrue
321     \ifx\lst@framelshape\@empty \let\lst@frameL\@empty \fi
322     \ifx\lst@framershape\@empty \let\lst@frameR\@empty \fi
323     \def\lst@framevrule{\vrule\@width\lst@framerulewidth\relax}%
324     \lst@ifframeround
325         \lst@frameCalcDimA\z@ \@getcirc\@tempdima
326         \@tempdimb\@tempdima \divide\@tempdimb\tw@
327         \advance\@tempdimb -\@wholewidth
328         \edef\lst@frametextsep{\the\@tempdimb}%
329         \edef\lst@framerulewidth{\the\@wholewidth}%
330         \lst@frameCalcDimA\@ne \@getcirc\@tempdima
331         \@tempdimb\@tempdima \divide\@tempdimb\tw@
332         \advance\@tempdimb -\tw@\@wholewidth
333         \advance\@tempdimb -\lst@frametextsep
334         \edef\lst@rulesep{\the\@tempdimb}%
335     \fi
336     \lst@frameMakeBoxV\lst@framebox{\ht\strutbox}{\dp\strutbox}%
337     %%%%  ここから
338     \@tempdima\z@
339     \ifdim\ht\strutbox<\cht\@tempdima=\dimexpr\cht-\ht\strutbox\relax\fi
340     \ifdim\dp\strutbox<\cdp\@tempdima=\dimexpr\cdp-\dp\strutbox\relax\fi
341     \ltj@lst@frame@lslimit=-\@tempdima
342     \def\lst@framelr{%
343       \ifltj@lst@frame@top\ltj@lst@frame@topfalse\else\lineskiplimit\ltj@lst@frame@lslimit\fi
344       \copy\lst@framebox}%
345     %%%% ここまで
346     \ifx\lst@frametshape\@empty\else
347         \lst@frameH T\lst@frametshape
348         \ifvoid\z@\else
349             \par\lst@parshape
350             \@tempdima-\baselineskip \advance\@tempdima\ht\z@
351             \ifdim\prevdepth<\@cclvi\p@\else
352                 \advance\@tempdima\prevdepth
353             \fi
354             \ifdim\@tempdima<\z@
355                 \vskip\@tempdima\vskip\lineskip
356             \fi
357             \noindent\box\z@\par
358             \lineskiplimit\maxdimen \lineskip\z@
359         \fi
360         \lst@frameSpreadV\lst@framextopmargin
361     \fi}
362
363
364
365 %%%%%%%%%%%%%%%% escape to \LaTeX
366 \lstloadaspects{escape}
367 \gdef\lst@Escape#1#2#3#4{%
368     \lst@CArgX #1\relax\lst@CDefX
369         {}%
370         {\lst@ifdropinput\else
371          \lst@TrackNewLines\lst@OutputLostSpace \lst@XPrintToken
372          \lst@InterruptModes
373          \lst@EnterMode{\lst@TeXmode}{\lst@modetrue}%
374          \ifx\^^M#2%
375              \lst@CArg #2\relax\lst@ActiveCDefX
376                  {}%
377                  {\lst@escapeend #4\lst@LeaveAllModes\lst@ReenterModes}%
378                  {\lst@MProcessListing}%
379          \else
380              \lst@CArg #2\relax\lst@ActiveCDefX
381                  {}%
382                  {\lst@escapeend #4\lst@LeaveAllModes\lst@ReenterModes
383                   \lst@newlines\z@ \lst@whitespacefalse}%
384                  {}%
385          \fi%
386          \ltj@lst@escape@setup#2%
387          #3\catcode\ltjlineendcomment=9\lst@escapebegin\expandafter\lst@next%"
388          \fi}%
389         {}}
390 \def\ltj@lst@emptygrp{{}}
391 \def\ltj@lst@escape@setup#1{%
392   \begingroup\lccode`\~=`#1\lowercase{%
393   \gdef\lst@next##1~{%
394      \let\lst@arg\@empty\ltj@lst@remove@jacmd{##1}%
395      \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
396            \scantokens\expandafter\expandafter\expandafter{\expandafter\ltj@lst@emptygrp\lst@arg\empty}%
397      ~}%
398   }\endgroup
399 }
400 \begingroup
401   \lccode`\|=\ltjlineendcomment \lowercase{%"
402   \gdef\ltj@lst@remove@jacmd#1{%
403     \expandafter\ltj@lst@remove@jacmd@\detokenize{#1}|\@nil|}
404   \gdef\ltj@lst@remove@jacmd@#1|{%
405     \ifx#1\@nil\else
406        \lst@lAddTo\lst@arg{#1}%
407        \expandafter\ltj@lst@remove@jacmd@
408     \fi}}
409 \endgroup
410
411 %%%%%%%%%%%%%%%% texcl
412 \lst@AddToHook{AfterBeginComment}
413    {\ifnum\lst@mode=\lst@TeXLmode
414       \catcode`\^^M=13\relax
415       \catcode\ltjlineendcomment=9\relax
416     \fi}
417
418 %%%%%%%%%%%%%%%%
419 \lstloadaspects{writefile}
420 \begingroup \catcode`\^^I=11
421 \gdef\lst@WFBegin#1#2{%
422     \begingroup
423     \let\lst@OutputBox#1%
424     \def\lst@Append##1{%
425         \advance\lst@length\@ne
426         \expandafter\lst@token\expandafter{\the\lst@token##1}%
427         \ifx ##1\lst@outputspace \else
428             \lst@WFAppend##1%
429         \fi}%
430     \lst@lAddTo\lst@PreGotoTabStop{\lst@WFAppend{^^I}}%
431     \lst@lAddTo\lst@ProcessSpace{\lst@WFAppend{ }}%
432     \def\ltj@lst@ProcessIVS##1{\lst@whitespacefalse\lst@Append##1}%
433     \def\ltj@lst@ProcessVS##1{\lst@whitespacefalse\lst@Append##1}%
434     \let\lst@DeInit\lst@WFDeInit
435     \let\lst@MProcessListing\lst@WFMProcessListing
436     \lst@WFifopen\else
437         \immediate\openout\lst@WF=#2\relax
438         \global\let\lst@WFifopen\iftrue
439         \@gobbletwo\fi\fi
440     \fi}
441 \endgroup
442
443 %    \begin{修正事項}{1.3} from jlisting.sty
444 % ちょっとした修正
445 \gdef\lst@breakProcessOther#1{\lst@ProcessOther#1}
446 % ソースコード目次における文字と番号の空き
447 \let \l@lstlisting = \l@figure
448
449 %%%% 
450 % キャプションとソースコード目次に対する日本語対応
451 %\def\lstlistingname{ソースコード}
452 %\def\lstlistlistingname{ソースコード目次}
453 %    \end{修正事項}
454 %%%%
455
456 \endinput