Skip to content

Commit e8efd18

Browse files
committed
Experimental \sphinxbreakablebox [skip ci]
1 parent ee3c720 commit e8efd18

1 file changed

Lines changed: 195 additions & 0 deletions

File tree

sphinx/texinputs/sphinxpackageboxes.sty

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,201 @@
277277
\fi
278278
}
279279

280+
% Experimental "breakable" variant. Use at own risk: either it works for your
281+
% use case and then you are fine, or it does not, then use \sphinxbox, or some
282+
% external to Sphinx approaches, such as the lua-hl package for LuaLaTeX only.
283+
%
284+
% These utilities will have to be used in a scope limiting context, else I
285+
% have to add some macro to store and restore a given configuration.
286+
\def\spx@boxes@fcolorbox@setup@openright{%
287+
\spx@boxes@border@right \z@
288+
\spx@boxes@padding@right \z@
289+
\spx@boxes@radius@topright \z@
290+
\spx@boxes@radius@bottomright\z@
291+
% external shadow handling will be complicated
292+
% but if it is on right side it should simply
293+
% work; if on left, then problems a hook should
294+
% be added to shadow drawing
295+
\ifspx@boxes@withshadow
296+
\ifspx@boxes@insetshadow
297+
\ifdim\spx@boxes@shadow@xoffset<\z@
298+
\spx@boxes@shadow@xoffset=\z@
299+
\fi
300+
\fi
301+
\fi
302+
\spx@boxes@fcolorbox@setup@fcolorbox
303+
}%
304+
\def\spx@boxes@fcolorbox@setup@openleft{%
305+
\spx@boxes@border@left \z@
306+
\spx@boxes@padding@left \z@
307+
\spx@boxes@radius@topleft \z@
308+
\spx@boxes@radius@bottomleft\z@
309+
\ifspx@boxes@withshadow
310+
\ifspx@boxes@insetshadow
311+
\ifdim\spx@boxes@shadow@xoffset>\z@
312+
\spx@boxes@shadow@xoffset=\z@
313+
\fi
314+
\fi
315+
\spx@boxes@fcolorbox@setup@fcolorbox
316+
}%
317+
\def\spx@boxes@fcolorbox@setup@openboth{%
318+
\spx@boxes@border@left \z@
319+
\spx@boxes@border@right \z@
320+
\spx@boxes@padding@left \z@
321+
\spx@boxes@padding@right \z@
322+
\spx@boxes@radius@topright \z@
323+
\spx@boxes@radius@bottomright\z@
324+
\spx@boxes@radius@topleft \z@
325+
\spx@boxes@radius@bottomleft \z@
326+
\ifspx@boxes@withshadow
327+
\ifspx@boxes@insetshadow
328+
\spx@boxes@shadow@xoffset\z@
329+
\fi
330+
\fi
331+
\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}%
332+
}%
333+
334+
335+
\catcode`Z=3 % safe delimiter
336+
\newcommand\sphinxbreakablebox[2][]{% #1 stands for the options, they are... optional!
337+
% for this first version I will assume the input has at least 2 characters
338+
\begingroup
339+
% this borrows a box from sphinxlatexliterals, \sphinxafterbreak will insert it
340+
% the original default from verbatimcontinued occupies some place and is red and
341+
% uses \tiny. Of course this here should be made customizable
342+
\sbox\sphinxcontinuationbox {\llap{\textcolor{gray}{$\m@th\hookrightarrow$ }}}%
343+
\sphinxboxsetup{#1}%
344+
\spx@boxes@fcolorbox@setup
345+
{box}
346+
{sphinxboxBorderColor}
347+
{sphinxboxBgColor}
348+
{sphinxboxShadowColor}%
349+
%%% \spx@boxes@shadowinbboxtrue%%% only for last one assume shadow on right if exists
350+
\def\spx@boxes@breakable@localsetup{\spx@boxes@fcolorbox@setup@openright}%
351+
\spx@boxes@breakable@a #2Z%
352+
}
353+
\def\spx@boxes@breakable@a{\futurelet\spx@nexttoken\spx@boxes@breakable@b}
354+
\def\spx@boxes@breakable@b{%
355+
\ifcat\noexpand\spx@nexttoken\relax
356+
\def\next{\spx@boxes@breakable@casei}%
357+
% as this is the most annoying branch its code is given last below
358+
\else
359+
\ifx\spx@nexttoken\bgroup
360+
% naked braced material, should never happen in Sphinx I think
361+
% we will handle this by removing the brace pair and start again
362+
\def\next{\spx@boxes@breakable@caseii}%
363+
\else
364+
\ifx\spx@nexttoken\@sptoken
365+
% a space, so it was following some character or {} and
366+
% we will handle this basically as we handle a single character
367+
\def\next{\spx@boxes@breakable@caseiii}%
368+
\else
369+
% hopefully some character token
370+
\def\next{\spx@boxes@breakable@mainloop}%
371+
\fi\fi\fi
372+
\next
373+
}%
374+
% some braced material; impossible in Sphinx a priori. Unbrace and proceed.
375+
\def\spx@boxes@breakable@caseii#1{\spx@boxes@breakable@a #1}
376+
% handle the blank space
377+
\@firstofone{\def\spx@boxes@breakable@caseiii} {\spx@boxes@breakable@mainloop{ }}
378+
% the simple case
379+
\def\spx@boxes@breakable@mainloop #1{%
380+
% need to check if at end; and add a strut to equalize heights
381+
\def\spx@temp{{#1\strut}}%
382+
\futurelet\spx@nexttoken\spx@boxes@breakable@check
383+
}
384+
\def\spx@boxes@breakable@check{%
385+
\ifx\spx@nexttoken Z%
386+
\def\spx@boxes@breakable@again Z{\endgroup}%
387+
\def\spx@boxes@breakable@localsetup{%
388+
\spx@boxes@shadowinbboxtrue
389+
\spx@boxes@fcolorbox@setup@openleft
390+
}%
391+
\fi
392+
{\spx@boxes@breakable@localsetup\expandafter\spx@boxes@fcolorbox\spx@temp}%
393+
\spx@boxes@breakable@again
394+
}
395+
\def\spx@boxes@breakable@again{%
396+
\discretionary{}{\sphinxafterbreak}{}%
397+
\def\spx@boxes@breakable@localsetup{\spx@boxes@fcolorbox@setup@openboth}%
398+
\futurelet\spx@nexttoken\spx@boxes@breakable@b
399+
}
400+
\let\spx@boxes@breakable@@again\spx@boxes@breakable@again
401+
% The more complex branch
402+
\def\spx@boxes@breakable@casei #1{%
403+
\ifcat\noexpand~\noexpand#1\relax% active character
404+
\expandafter\spx@boxes@breakable@casei@active
405+
\else % some control sequence; if a LaTeX escape assumed followed by an empty
406+
% brace pair {}. If a macro assumed to be one with exactly one argument...
407+
\expandafter\spx@boxes@breakable@casei@b
408+
\fi #1%
409+
}%
410+
% assume active character can ONLY come from utf-8 in pdflatex...
411+
% ...if not we are doomed here
412+
\def\spx@boxes@breakable@casei@active#1{%
413+
\expandafter\spx@boxes@breakable@casei@active@a#1Z#1%
414+
}%
415+
% I use \def's not \let's only for easier debugging via log trace if needed
416+
\def\spx@boxes@breakable@casei@active@a #1#2Z{%
417+
\ifx\UTFviii@four@octets#1\def\next{\spx@boxes@breakable@four}\else
418+
\ifx\UTFviii@three@octet#1\def\next{\spx@boxes@breakable@three}\else
419+
\ifx\UTFviii@two@octets #1\def\next{\spx@boxes@breakable@two}\else
420+
\def\next{\spx@boxes@breakable@mainloop}%
421+
\fi\fi\fi
422+
\next
423+
}%
424+
\def\spx@boxes@breakable@two #1#2{\spx@boxes@breakable@mainloop{#1#2}}%
425+
\def\spx@boxes@breakable@three #1#2#3{\spx@boxes@breakable@mainloop{#1#2#3}}%
426+
\def\spx@boxes@breakable@four #1#2#3#4{\spx@boxes@breakable@mainloop{#1#2#3#4}}%
427+
%
428+
\def\spx@boxes@breakable@casei@b #1#2{%
429+
% **assume #1 is a one-argument** macro, probably some macro ending-up doing
430+
% some \textit etc... OR some LaTeX escape of a character special to
431+
% LaTeX (which I think is then always followed by {} from Sphinx
432+
% mark-up. TODO: check if the case).
433+
% CAVEAT: a \sphinxhref which has two arguments **will cause breakage**.
434+
% TODO: check for \sphinxhref and handle it if possible.
435+
\def\spx@tempa{#1}%
436+
\def\spx@tempb{#2}%
437+
\futurelet\spx@nexttoken\spx@boxes@breakable@casei@checkandloop
438+
}
439+
\def\spx@boxes@breakable@casei@checkandloop{%
440+
\ifx\spx@nexttoken Z%
441+
\def\spx@boxes@breakable@again Z{\endgroup}%
442+
\def\spx@boxes@breakable@localsetup{%
443+
\spx@boxes@shadowinbboxtrue
444+
\spx@boxes@fcolorbox@setup@openleft
445+
}%
446+
\fi
447+
\if\relax\detokenize\expandafter{\spx@tempb}\relax
448+
% seems #1 is some latex escape of a special character, was followed by {}
449+
{\spx@boxes@breakable@localsetup
450+
\expandafter\spx@boxes@fcolorbox\expandafter{\spx@tempa\strut}}%
451+
\else
452+
% #1 was some macro with non-empty argument, try something crazy
453+
% problematic if the macro argument #2 is a single character
454+
% breakage if #1 is a multiple-argument macro
455+
% should work if #1 is some \textit for example. Hopefully.
456+
\spx@tempa{\begingroup
457+
\let\spx@boxes@breakable@again\spx@boxes@breakable@@again
458+
% inhibit the sub-thing to terminate with an openleft
459+
\def\spx@boxes@fcolorbox@setup@openleft{\spx@boxes@fcolorbox@setup@openboth}%
460+
% what a hack... let true be false
461+
\def\spx@boxes@shadowinbboxtrue{\expandafter\let\csname
462+
ifspx@boxes@shadowinbbox\expandafter\endcsname
463+
\csname iffalse\endcsname}%
464+
% we may start here in openright or already openboth state
465+
\expandafter\spx@boxes@breakable@a\spx@tempb Z}%
466+
\fi
467+
\spx@boxes@breakable@again
468+
}
469+
470+
\catcode`Z 11 %
471+
%
472+
473+
474+
280475
%%%%%%%%%%%%%%%%
281476
% MACROS
282477
%

0 commit comments

Comments
 (0)