|
277 | 277 | \fi |
278 | 278 | } |
279 | 279 |
|
| 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 | + |
280 | 475 | %%%%%%%%%%%%%%%% |
281 | 476 | % MACROS |
282 | 477 | % |
|
0 commit comments