• Tidak ada hasil yang ditemukan

Format definitions*

Dalam dokumen The Listings Package (Halaman 162-168)

dialect. Thanks to Walter E. Brown for reporting a problem with the argument delimiter ‘[’ in a previous definition of\lstalias@.

2378\lst@UserCommand\lstalias{\@ifnextchar[\lstalias@\lstalias@@}

2379\gdef\lstalias@[#1]#2{\lstalias@b #2$#1}

2380\gdef\lstalias@b#1[#2]#3{\lst@NormedNameDef{lsta@#1}{#3$#2}}

2381\gdef\lstalias@@#1#2{\lst@NormedNameDef{lsta@#1}{#2}}

defaultdialect We simply store the dialect.

2382\lst@Key{defaultdialect}\relax

2383 {\lstKV@OptArg[]{#1}{\lst@NormedNameDef{lstdd@##2}{##1}}}

\lst@FindAlias Now we have to find a language. First we test for a complete language alias, then we set the default dialect if necessary.

2384\gdef\lst@FindAlias[#1]#2{%

2385 \lst@NormedDef\lst@oalias{#1}%

2386 \lst@NormedDef\lst@malias{#2}%

2387 \@ifundefined{lsta@\lst@malias}{}%

2388 {\edef\lst@malias{\csname\@lst a@\lst@malias\endcsname}}%

2389 \ifx\@empty\lst@oalias \@ifundefined{lstdd@\lst@malias}{}%

2390 {\edef\lst@oalias{\csname\@lst dd@\lst@malias\endcsname}}%

2391 \fi

Now we are ready for an alias of a single dialect.

2392 \edef\lst@temp{\lst@malias $\lst@oalias}%

2393 \@ifundefined{lsta@\lst@temp}{}%

2394 {\edef\lst@temp{\csname\@lst a@\lst@temp\endcsname}}%

Finally we again set the default dialect—for the case of a dialect alias.

2395 \expandafter\lst@FindAlias@\lst@temp $}

2396\gdef\lst@FindAlias@#1$#2${%

2397 \def\lst@malias{#1}\def\lst@oalias{#2}%

2398 \ifx\@empty\lst@oalias \@ifundefined{lstdd@\lst@malias}{}%

2399 {\edef\lst@oalias{\csname\@lst dd@\lst@malias\endcsname}}%

2400 \fi}

\lst@RequireLanguages This definition will be equivalent to\lstloadlanguages. We requested the given list of languages and load additionally required aspects.

2401\gdef\lst@RequireLanguages#1{%

2402 \lst@Require{language}{lang}{#1}\lst@FindAlias\lstlanguagefiles

2403 \ifx\lst@loadaspects\@empty\else

2404 \lst@RequireAspects\lst@loadaspects

2405 \fi}

\lstloadlanguages is the same as\lst@RequireLanguages.

2406\global\let\lstloadlanguages\lst@RequireLanguages

2407\lst@EndAspect

2408h/misci

\lstformatfiles This macro is defined if and only if it’s undefined yet.

2411\@ifundefined{lstformatfiles}

2412 {\lst@UserCommand\lstformatfiles{lstfmt0.sty}}{}

\lstdefineformat

\lst@defineformat

\lst@DefFormat

are defined in terms of\lst@DefFormat, which is defined via\lst@DefDriver.

2413\lst@UserCommand\lstdefineformat{\lst@DefFormat\iftrue}

2414\lst@UserCommand\lst@defineformat{\lst@DefFormat\iffalse}

2415\gdef\lst@DefFormat{\lst@DefDriver{format}{fmt}\lst@UseFormat}

We provide the ‘empty’ format.

2416\lstdefineformat{}{}

format is an application of \lst@LAS. We just specify the hook as ‘pre’ and an empty argument as ‘post’ code.

2417\lst@Key{format}\relax{%

2418 \lst@LAS{format}{fmt}{[]{#1}}\lst@NoAlias\lstformatfiles

2419 \lsthk@SetFormat

2420 {}}

2421\lst@AddToHook{SetFormat}{\let\lst@fmtformat\@empty}% init

Helpers Our goal is to define the yet unkown\lst@UseFormat. This definition will parse the user supplied format. We start with some general macros.

\lst@fmtSplit splits the content of the macro#1at#2in the preceding characters\lst@fmtaand the following ones \lst@fmtb. \lst@if is false if and only if#1doesn’t contain

#2.

2422\gdef\lst@fmtSplit#1#2{%

2423 \def\lst@temp##1#2##2\relax##3{%

2424 \ifnum##3=\z@

2425 \ifx\@empty##2\@empty

2426 \lst@false

2427 \let\lst@fmta#1%

2428 \let\lst@fmtb\@empty

2429 \else

2430 \expandafter\lst@temp#1\relax\@ne

2431 \fi

2432 \else

2433 \def\lst@fmta{##1}\def\lst@fmtb{##2}%

2434 \fi}%

2435 \lst@true

2436 \expandafter\lst@temp#1#2\relax\z@}

\lst@IfNextCharWhitespace is defined in terms of\lst@IfSubstring.

2437\gdef\lst@IfNextCharWhitespace#1#2#3{%

2438 \lst@IfSubstring#3\lst@whitespaces{#1}{#2}#3}

And here come all white space characters.

2439\begingroup

2440\catcode‘\^^I=12\catcode‘\^^J=12\catcode‘\^^M=12\catcode‘\^^L=12\relax%

2441\lst@DefActive\lst@whitespaces{\ ^^I^^J^^M}% add ^^L

2442\global\let\lst@whitespaces\lst@whitespaces%

2443\endgroup

\lst@fmtIfIdentifier tests the first character of#1

2444\gdef\lst@fmtIfIdentifier#1{%

2445 \ifx\relax#1\@empty

2446 \expandafter\@secondoftwo

2447 \else

2448 \expandafter\lst@fmtIfIdentifier@\expandafter#1%

2449 \fi}

against the ‘letters’_,@,A,. . . ,Zanda,. . . ,z.

2450\gdef\lst@fmtIfIdentifier@#1#2\relax{%

2451 \let\lst@next\@secondoftwo

2452 \ifnum‘#1=‘_\else

2453 \ifnum‘#1<64\else

2454 \ifnum‘#1<91\let\lst@next\@firstoftwo\else

2455 \ifnum‘#1<97\else

2456 \ifnum‘#1<123\let\lst@next\@firstoftwo\else

2457 \fi \fi \fi \fi \fi

2458 \lst@next}

\lst@fmtIfNextCharIn is required for the optionalhexceptional charactersi. The implementation is easy—

refer section 13.1.

2459\gdef\lst@fmtIfNextCharIn#1{%

2460 \ifx\@empty#1\@empty \expandafter\@secondoftwo \else

2461 \def\lst@next{\lst@fmtIfNextCharIn@{#1}}%

2462 \expandafter\lst@next\fi}

2463\gdef\lst@fmtIfNextCharIn@#1#2#3#4{%

2464 \def\lst@temp##1#4##2##3\relax{%

2465 \ifx \@empty##2\expandafter\@secondoftwo

2466 \else \expandafter\@firstoftwo \fi}%

2467 \lst@temp#1#4\@empty\relax{#2}{#3}#4}

\lst@fmtCDef We need derivations of\lst@CDefand\lst@CDefX: we have to test the next char- acter against the sequence #5of exceptional characters. These tests are inserted here.

2468\gdef\lst@fmtCDef#1{\lst@fmtCDef@#1}

2469\gdef\lst@fmtCDef@#1#2#3#4#5#6#7{%

2470 \lst@CDefIt#1{#2}{#3}%

2471 {\lst@fmtIfNextCharIn{#5}{#4#2#3}{#6#4#2#3#7}}%

2472 #4%

2473 {}{}{}}

\lst@fmtCDefX The same but ‘drop input’.

2474\gdef\lst@fmtCDefX#1{\lst@fmtCDefX@#1}

2475\gdef\lst@fmtCDefX@#1#2#3#4#5#6#7{%

2476 \let#4#1%

2477 \ifx\@empty#2\@empty

2478 \def#1{\lst@fmtIfNextCharIn{#5}{#4}{#6#7}}%

2479 \else \ifx\@empty#3\@empty

2480 \def#1##1{%

2481 \ifx##1#2%

2482 \def\lst@next{\lst@fmtIfNextCharIn{#5}{#4##1}%

2483 {#6#7}}%

2484 \else

2485 \def\lst@next{#4##1}%

2486 \fi

2487 \lst@next}%

2488 \else

2489 \def#1{%

2490 \lst@IfNextCharsArg{#2#3}%

2491 {\lst@fmtIfNextCharIn{#5}{\expandafter#4\lst@eaten}%

2492 {#6#7}}%

2493 {\expandafter#4\lst@eaten}}%

2494 \fi \fi}

The parser applies\lst@fmtSplitto cut a format definition into items, items into ‘input’ and ‘output’, and ‘output’ into ‘pre’ and ’post’. This should be clear if you are in touch with format definitions.

\lst@UseFormat Now we can start with the parser.

2495\gdef\lst@UseFormat#1{%

2496 \def\lst@fmtwhole{#1}%

2497 \lst@UseFormat@}

2498\gdef\lst@UseFormat@{%

2499 \lst@fmtSplit\lst@fmtwhole,%

We assign the rest of the format definition, . . .

2500 \let\lst@fmtwhole\lst@fmtb

2501 \ifx\lst@fmta\@empty\else

. . . split the item at the equal sign, and work on the item.

2502 \lst@fmtSplit\lst@fmta=%

2503 \ifx\@empty\lst@fmta\else

To do: Insert \let\lst@arg\@empty \expandafter\lst@XConvert\lst@fmtb\@nil

\let\lst@fmtb\lst@arg.

2504 \expandafter\lstKV@XOptArg\expandafter[\expandafter]%

2505 \expandafter{\lst@fmtb}\lst@UseFormat@b

2506 \fi

2507 \fi

Finally we process the next item if the rest is not empty.

2508 \ifx\lst@fmtwhole\@empty\else

2509 \expandafter\lst@UseFormat@

2510 \fi}

We make \lst@fmtccontain the preceding characters as a braced argument. To add more arguments, we first split the replacement tokens at the control sequence

\string.

2511\gdef\lst@UseFormat@b[#1]#2{%

2512 \def\lst@fmtc{{#1}}\lst@lExtend\lst@fmtc{\expandafter{\lst@fmta}}%

2513 \def\lst@fmtb{#2}%

2514 \lst@fmtSplit\lst@fmtb\string

We append an empty argument or\lst@fmtPrewith ‘\string-preceding’ tokens as argument. We do the same for the tokens after\string.

2515 \ifx\@empty\lst@fmta

2516 \lst@lAddTo\lst@fmtc{{}}%

2517 \else

2518 \lst@lExtend\lst@fmtc{\expandafter

2519 {\expandafter\lst@fmtPre\expandafter{\lst@fmta}}}%

2520 \fi

2521 \ifx\@empty\lst@fmtb

2522 \lst@lAddTo\lst@fmtc{{}}%

2523 \else

2524 \lst@lExtend\lst@fmtc{\expandafter

2525 {\expandafter\lst@fmtPost\expandafter{\lst@fmtb}}}%

2526 \fi

Eventually we extend \lst@fmtformat appropriately. Note that \lst@if still indicates whether the replacement tokens contain\string.

2527 \expandafter\lst@UseFormat@c\lst@fmtc}

2528\gdef\lst@UseFormat@c#1#2#3#4{%

2529 \lst@fmtIfIdentifier#2\relax

2530 {\lst@fmtIdentifier{#2}%

2531 \lst@if\else \PackageWarning{Listings}%

2532 {Cannot drop identifier in format definition}%

2533 \fi}%

2534 {\lst@if

2535 \lst@lAddTo\lst@fmtformat{\lst@CArgX#2\relax\lst@fmtCDef}%

2536 \else

2537 \lst@lAddTo\lst@fmtformat{\lst@CArgX#2\relax\lst@fmtCDefX}%

2538 \fi

2539 \lst@DefActive\lst@fmtc{#1}%

2540 \lst@lExtend\lst@fmtformat{\expandafter{\lst@fmtc}{#3}{#4}}}}

2541\lst@AddToHook{SelectCharTable}{\lst@fmtformat}

2542\global\let\lst@fmtformat\@empty The formatting

\lst@fmtPre

2543\gdef\lst@fmtPre#1{%

2544 \lst@PrintToken

2545 \begingroup

2546 \let\newline\lst@fmtEnsureNewLine

2547 \let\space\lst@fmtEnsureSpace

2548 \let\indent\lst@fmtIndent

2549 \let\noindent\lst@fmtNoindent

2550 #1%

2551 \endgroup}

\lst@fmtPost

2552\gdef\lst@fmtPost#1{%

2553 \global\let\lst@fmtPostOutput\@empty

2554 \begingroup

2555 \def\newline{\lst@AddTo\lst@fmtPostOutput\lst@fmtEnsureNewLine}%

2556 \def\space{\aftergroup\lst@fmtEnsurePostSpace}%

2557 \def\indent{\lst@AddTo\lst@fmtPostOutput\lst@fmtIndent}%

2558 \def\noindent{\lst@AddTo\lst@fmtPostOutput\lst@fmtNoindent}%

2559 \aftergroup\lst@PrintToken

2560 #1%

2561 \endgroup}

2562\lst@AddToHook{Init}{\global\let\lst@fmtPostOutput\@empty}

2563\lst@AddToHook{PostOutput}

2564 {\lst@fmtPostOutput \global\let\lst@fmtPostOutput\@empty}

\lst@fmtEnsureSpace

\lst@fmtEnsurePostSpace2565\gdef\lst@fmtEnsureSpace{%

2566 \lst@ifwhitespace\else \expandafter\lst@ProcessSpace \fi}

2567\gdef\lst@fmtEnsurePostSpace{%

2568 \lst@IfNextCharWhitespace{}{\lst@ProcessSpace}}

fmtindent

\lst@fmtIndent

\lst@fmtNoindent

2569\lst@Key{fmtindent}{20pt}{\def\lst@fmtindent{#1}}

2570\newdimen\lst@fmtcurrindent

2571\lst@AddToHook{InitVars}{\global\lst@fmtcurrindent\z@}

2572\gdef\lst@fmtIndent{\global\advance\lst@fmtcurrindent\lst@fmtindent}

2573\gdef\lst@fmtNoindent{\global\advance\lst@fmtcurrindent-\lst@fmtindent}

\lst@fmtEnsureNewLine

2574\gdef\lst@fmtEnsureNewLine{%

2575 \global\advance\lst@newlines\@ne

2576 \global\advance\lst@newlinesensured\@ne

2577 \lst@fmtignoretrue}

2578\lst@AddToAtTop\lst@DoNewLines{%

2579 \ifnum\lst@newlines>\lst@newlinesensured

2580 \global\advance\lst@newlines-\lst@newlinesensured

2581 \fi

2582 \global\lst@newlinesensured\z@}

2583\newcount\lst@newlinesensured % global

2584\lst@AddToHook{Init}{\global\lst@newlinesensured\z@}

2585\gdef\lst@fmtignoretrue{\let\lst@fmtifignore\iftrue}

2586\gdef\lst@fmtignorefalse{\let\lst@fmtifignore\iffalse}

2587\lst@AddToHook{InitVars}{\lst@fmtignorefalse}

2588\lst@AddToHook{Output}{\lst@fmtignorefalse}

\lst@fmtUseLostSpace

2589\gdef\lst@fmtUseLostSpace{%

2590 \lst@ifnewline \kern\lst@fmtcurrindent \global\lst@lostspace\z@

2591 \else

2592 \lst@OldOLS

2593 \fi}

2594\lst@AddToHook{Init}

2595 {\lst@true

2596 \ifx\lst@fmtformat\@empty \ifx\lst@fmt\@empty \lst@false \fi\fi

2597 \lst@if

2598 \let\lst@OldOLS\lst@OutputLostSpace

2599 \let\lst@OutputLostSpace\lst@fmtUseLostSpace

2600 \let\lst@ProcessSpace\lst@fmtProcessSpace

2601 \fi}

To do: This ‘lost space’ doesn’t use\lst@alloverstyleyet!

\lst@fmtProcessSpace

2602\gdef\lst@fmtProcessSpace{%

2603 \lst@ifletter

2604 \lst@Output

2605 \lst@fmtifignore\else

2606 \lst@AppendOther\lst@outputspace

2607 \fi

2608 \else \lst@ifkeepspaces

2609 \lst@AppendOther\lst@outputspace

2610 \else \ifnum\lst@newlines=\z@

2611 \lst@AppendSpecialSpace

2612 \else \ifnum\lst@length=\z@

2613 \global\advance\lst@lostspace\lst@width

2614 \global\advance\lst@pos\m@ne

2615 \else

2616 \lst@AppendSpecialSpace

2617 \fi

2618 \fi \fi \fi

2619 \lst@whitespacetrue}

Formatting identifiers

\lst@fmtIdentifier We install a (keyword) test for the ‘format identifiers’.

2620\lst@InstallTest{f}

2621 \lst@fmt@list\lst@fmt \lst@gfmt@list\lst@gfmt

2622 \lst@gfmt@wp

2623 wd

2624\gdef\lst@fmt@list{\lst@fmt\lst@gfmt}\global\let\lst@fmt\@empty

2625\gdef\lst@gfmt@list{\lst@fmt\lst@gfmt}\global\let\lst@gfmt\@empty

The working procedure expands\lst@fmt$hstringi(and defines\lst@PrintToken to do nothing).

2626\gdef\lst@gfmt@wp{%

2627 \begingroup \let\lst@UM\@empty

2628 \let\lst@PrintToken\@empty

2629 \csname\@lst @fmt$\the\lst@token\endcsname

2630 \endgroup}

This control sequence is probably defined as ‘working identifier’.

2631\gdef\lst@fmtIdentifier#1#2#3#4{%

2632 \lst@DefOther\lst@fmta{#2}\edef\lst@fmt{\lst@fmt,\lst@fmta}%

2633 \@namedef{\@lst @fmt$\lst@fmta}{#3#4}}

\lst@fmt$hidentifieriexpands to a\lst@fmtPre/\lst@fmtPostsequence defined by#2and#3.

2634\lst@EndAspect

2635h/misci

Dalam dokumen The Listings Package (Halaman 162-168)