Fix newfangle.module, fix generation of non-defined languages
[newfangle.git] / newfangle.lyx
blobfb33dea160f65ad0424bdd7f9a92590790a81911
1 #LyX 1.6.4 created this file. For more info see http://www.lyx.org/
2 \lyxformat 345
3 \begin_document
4 \begin_header
5 \textclass book
6 \begin_preamble
7 %\usepackage{xcolor}
8 %\definecolor{darkgreen}{rgb}{0,0.5,0}
9 \lstset{numbers=left, stepnumber=1, numbersep=5pt, breaklines=false,
10 basicstyle=\footnotesize\ttfamily,
11 %keywordstyle=\color{darkgreen},
12 numberstyle=\tiny,language=C,columns=fullflexible,
13 numberfirstline=true}
14 \end_preamble
15 \use_default_options true
16 \begin_modules
17 logicalmkup
18 newfangle
19 \end_modules
20 \language english
21 \inputencoding auto
22 \font_roman default
23 \font_sans default
24 \font_typewriter default
25 \font_default_family default
26 \font_sc false
27 \font_osf false
28 \font_sf_scale 100
29 \font_tt_scale 100
31 \graphics default
32 \paperfontsize default
33 \spacing single
34 \use_hyperref true
35 \pdf_title "Newfangle"
36 \pdf_author "Sam Liddicott"
37 \pdf_subject "Literate Programing"
38 \pdf_keywords "notangle noweb noweave literate programming cweb"
39 \pdf_bookmarks true
40 \pdf_bookmarksnumbered false
41 \pdf_bookmarksopen false
42 \pdf_bookmarksopenlevel 1
43 \pdf_breaklinks false
44 \pdf_pdfborder false
45 \pdf_colorlinks true
46 \pdf_backref false
47 \pdf_pdfusetitle true
48 \papersize default
49 \use_geometry false
50 \use_amsmath 1
51 \use_esint 1
52 \cite_engine basic
53 \use_bibtopic false
54 \paperorientation portrait
55 \secnumdepth 3
56 \tocdepth 3
57 \paragraph_separation skip
58 \defskip medskip
59 \quotes_language english
60 \papercolumns 1
61 \papersides 1
62 \paperpagestyle default
63 \tracking_changes false
64 \output_changes false
65 \author "" 
66 \author "" 
67 \end_header
69 \begin_body
71 \begin_layout Title
72 newfangle
73 \end_layout
75 \begin_layout Author
76 Sam Liddicott
77 \end_layout
79 \begin_layout Date
80 August 2009
81 \end_layout
83 \begin_layout Chapter*
84 Introduction
85 \end_layout
87 \begin_layout Standard
89 \noun on
90 Newfangle
91 \noun default
92  is a tool for newfangled literate programming.
93  Newfangled is defined as 
94 \emph on
95 New and often needlessly novel
96 \emph default
97  by 
98 \noun on
99 TheFreeDictionary.com
100 \noun default
102 \end_layout
104 \begin_layout Standard
105 In this case, newfangled means yet another new and improved method for literate
106  programming.
107 \end_layout
109 \begin_layout Standard
111 \noun on
112 Literate Programming
113 \noun default
114  has a long history starting with the great 
115 \noun on
116 Donald Knuth
117 \noun default
118  himself, whose literate programming tools seem to make use of as many escaped
119  abbreviations for semantic markup as TeX itself.
120 \end_layout
122 \begin_layout Standard
124 \noun on
125 Norman Ramsey
126 \noun default
127  wrote the 
128 \noun on
129 noweb
130 \noun default
131  set of tools (notangle, noweave and noroots) and helpfully reduced the
132  amount of magic character sequences to just 
133 \begin_inset Flex CharStyle:Code
134 status collapsed
136 \begin_layout Plain Layout
138 \end_layout
140 \end_inset
142  and 
143 \begin_inset Flex CharStyle:Code
144 status collapsed
146 \begin_layout Plain Layout
148 \end_layout
150 \end_inset
152 , and in doing so brought the wonders of literate programming within my
153  reach.
154 \end_layout
156 \begin_layout Standard
157 While using the LyX editor for LaTeX editing I had various troubles with
158  the noweb tools, some of which were my fault, some of which were noweb's
159  fault and some of which were LyX's fault.
160 \end_layout
162 \begin_layout Standard
164 \noun on
165 Noweb
166 \noun default
167  generally brought literate programming to the masses through removing some
168  of the complexity of the original literate programming, but this would
169  be of no advantage to me if the LyX / LaTeX combination brought more complicati
170 ons in their place.
171 \end_layout
173 \begin_layout Standard
175 \noun on
176 Newfangle
177 \noun default
178  was thus born --- as an awk replacement for notangle, adding some important
179  features, like better integration with LyX and LaTeX, multiple output format
180  conversions, and fixing notangle bugs like indentation when using -L for
181  line numbers.
182 \end_layout
184 \begin_layout Standard
185 Significantly, newfangle is just one program which replaces various programs
186  in Noweb.
187  Specifically noweave is done away with and implemented directly as LaTeX
188  macros, and noroots is implemented as a function of the untangler 
189 \noun on
190 newfangle
191 \noun default
193 \end_layout
195 \begin_layout Standard
196 Newfangle is written in awk for portability reasons, awk being available
197  for most platforms.
198  A python conversion will probably be attempted for the benefit of LyX.
199  (Hasn't anyone implemented awk in python yet?)
200 \end_layout
202 \begin_layout Standard
203 As an extension to many literate-programming styles, Newfangle permits code
204  chunks to take parameters and thus operate somewhat like C pre-processor
205  macros, or like C++ templates.
206 \end_layout
208 \begin_layout Section*
209 Todo
210 \end_layout
212 \begin_layout Enumerate
213 ^^ is always going to be a problem, see texbytopic 1.2.2 (Work out what I
214  meant by this).
215 \end_layout
217 \begin_layout Enumerate
218 copy over up to date Makefile guide from noweb-lyx document
219 \end_layout
221 \begin_layout Enumerate
222 Make chunk-name settings only apply to chunks with that name
223 \end_layout
225 \begin_layout Enumerate
226 indent of multi-line chunks may be mode dependant (i.e.
227  not in string literals)
228 \end_layout
230 \begin_layout Enumerate
231 support chunk-param usage =<
232 \backslash
233 param{name}>
234 \end_layout
236 \begin_layout Enumerate
237 trim spaces from param
238 \end_layout
240 \begin_layout Enumerate
241 add support for other commands in =<...>, starting with 
242 \backslash
243 label which takes the line-number within the chunk, and maybe should also
244  take the chunk name/page
245 \end_layout
247 \begin_layout Enumerate
248 cant have listing inside a ruled box
249 \end_layout
251 \begin_layout Enumerate
252 when a parameterized chunk is included as well as the #line emission, say
253  what the paremeters were for that invocation.
254 \end_layout
256 \begin_layout Enumerate
257 with 2 macro expansions on one line ${} ${} the first is too greedy and
258  looks to the final }
259 \end_layout
261 \begin_layout Enumerate
263 \backslash
264 chunkref[3]{preamble} to include a certain chunk needs to work in newfangle.awk
265  instead of failing to be recognized at all
266 \end_layout
268 \begin_layout Enumerate
269 make in-listins labels track the chunk ref too, and make 
270 \backslash
271 chunref{[2],thing}> resolve to 41c (or d, or whatever chunk the 2nd chunk
272  of thing is
273 \end_layout
275 \begin_layout Enumerate
277 \backslash
278 chunkref in text needs a trailing space maybe, it keeps butting up to the
279  next word
280 \end_layout
282 \begin_layout Enumerate
283 because the white-space indent is output by the parent chunk, the #line
284  is that of the parent chunk.
285  White space indents must be passed to the child chunk
286 \end_layout
288 \begin_layout Chapter*
289 License
290 \end_layout
292 \begin_layout Standard
293 \begin_inset CommandInset label
294 LatexCommand label
295 name "cha:License"
297 \end_inset
299 Newfangle is licensed under the GPL 3
300 \begin_inset CommandInset citation
301 LatexCommand cite
302 key "gpl-licenses"
304 \end_inset
306  (or later).
307  This doesn't mean that you can't use or distribute newfangle with sources
308  of an incompatible license, but it means you must make the source of newfangle
309  available too.
310 \end_layout
312 \begin_layout Chunk
313 gpl3-copyright,language=
314 \end_layout
316 \begin_layout Standard
317 \begin_inset listings
318 inline false
319 status open
321 \begin_layout Plain Layout
323 newfangle - fully featured notangle replacement in awk
324 \end_layout
326 \begin_layout Plain Layout
328 \end_layout
330 \begin_layout Plain Layout
332 Copyright (C) Sam Liddicott 2009
333 \end_layout
335 \begin_layout Plain Layout
337 \end_layout
339 \begin_layout Plain Layout
341 This program is free software: you can redistribute it and/or modify
342 \end_layout
344 \begin_layout Plain Layout
346 it under the terms of the GNU General Public License as published by
347 \end_layout
349 \begin_layout Plain Layout
351 the Free Software Foundation, either version 3 of the License, or
352 \end_layout
354 \begin_layout Plain Layout
356 (at your option) any later version.
357 \end_layout
359 \begin_layout Plain Layout
361 \end_layout
363 \begin_layout Plain Layout
365 This program is distributed in the hope that it will be useful,
366 \end_layout
368 \begin_layout Plain Layout
370 but WITHOUT ANY WARRANTY; without even the implied warranty of
371 \end_layout
373 \begin_layout Plain Layout
375 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
376   See the
377 \end_layout
379 \begin_layout Plain Layout
381 GNU General Public License for more details.
382 \end_layout
384 \begin_layout Plain Layout
386 \end_layout
388 \begin_layout Plain Layout
390 You should have received a copy of the GNU General Public License
391 \end_layout
393 \begin_layout Plain Layout
395 along with this program.
396   If not, see <http://www.gnu.org/licenses/>.
397 \end_layout
399 \begin_layout Plain Layout
401 \end_layout
403 \end_inset
406 \end_layout
408 \begin_layout Standard
409 \begin_inset CommandInset toc
410 LatexCommand tableofcontents
412 \end_inset
415 \end_layout
417 \begin_layout Part
418 Using Newfangle
419 \end_layout
421 \begin_layout Chapter
422 Running Newfangle
423 \end_layout
425 \begin_layout Standard
426 Newfangle is a replacement for noweb, which consists of 
427 \begin_inset Flex CharStyle:Code
428 status collapsed
430 \begin_layout Plain Layout
431 notangle
432 \end_layout
434 \end_inset
437 \begin_inset Flex CharStyle:Code
438 status collapsed
440 \begin_layout Plain Layout
441 noroots
442 \end_layout
444 \end_inset
446  and 
447 \begin_inset Flex CharStyle:Code
448 status collapsed
450 \begin_layout Plain Layout
451 noweave
452 \end_layout
454 \end_inset
457 \end_layout
459 \begin_layout Standard
460 Like 
461 \begin_inset Flex CharStyle:Code
462 status collapsed
464 \begin_layout Plain Layout
465 notangle
466 \end_layout
468 \end_inset
470  and 
471 \begin_inset Flex CharStyle:Code
472 status collapsed
474 \begin_layout Plain Layout
475 noroots
476 \end_layout
478 \end_inset
480  it can read multiple named files, or from stdin.
481 \end_layout
483 \begin_layout Section
484 Listing roots
485 \end_layout
487 \begin_layout Standard
488 The -r option causes newfangle to behave like noroots.
489 \end_layout
491 \begin_layout LyX-Code
492 newfangle -r filename.tex
493 \end_layout
495 \begin_layout Standard
496 will print out the newfangle roots of a tex file.
498 \end_layout
500 \begin_layout Standard
501 Unlike the 
502 \begin_inset Flex CharStyle:Code
503 status collapsed
505 \begin_layout Plain Layout
506 noroots
507 \end_layout
509 \end_inset
511  command, the roots are not enclosed in 
512 \begin_inset Flex CharStyle:Code
513 status collapsed
515 \begin_layout Plain Layout
516 <<name>>
517 \end_layout
519 \end_inset
521 , unless at least one of the roots is defined using the 
522 \begin_inset Flex CharStyle:Code
523 status collapsed
525 \begin_layout Plain Layout
526 notangle
527 \end_layout
529 \end_inset
531  style 
532 \begin_inset Flex CharStyle:Code
533 status collapsed
535 \begin_layout Plain Layout
536 <<name>>=
537 \end_layout
539 \end_inset
542 \end_layout
544 \begin_layout Standard
545 Also, unlike noroots, it prints out all roots --- not just those that are
546  not used elsewhere.
547  I find that a root not being used, doesn't make it particularly top level.
548  My convention is that top level roots to be extracted begin with 
549 \begin_inset Flex CharStyle:Code
550 status collapsed
552 \begin_layout Plain Layout
554 \end_layout
556 \end_inset
558  and have the form of a filename.
559 \end_layout
561 \begin_layout Section
562 Extracting roots
563 \end_layout
565 \begin_layout Standard
566 notangle's 
567 \begin_inset Flex CharStyle:Code
568 status collapsed
570 \begin_layout Plain Layout
572 \end_layout
574 \end_inset
576  and 
577 \begin_inset Flex CharStyle:Code
578 status collapsed
580 \begin_layout Plain Layout
582 \end_layout
584 \end_inset
586  options are supported.
587 \end_layout
589 \begin_layout Standard
590 The standard way to extract a file would be:
591 \end_layout
593 \begin_layout LyX-Code
594 newfangle -R./Makefile.inc newfangle.tex > ./Makefile.inc
595 \end_layout
597 \begin_layout Standard
598 Unlike the 
599 \begin_inset Flex CharStyle:Code
600 status collapsed
602 \begin_layout Plain Layout
603 noroots
604 \end_layout
606 \end_inset
608  command, the 
609 \begin_inset Flex CharStyle:Code
610 status collapsed
612 \begin_layout Plain Layout
614 \end_layout
616 \end_inset
618  option does not break indenting; also the 
619 \begin_inset Flex CharStyle:Code
620 status collapsed
622 \begin_layout Plain Layout
624 \end_layout
626 \end_inset
628  option does not interrupt (and break) multi-line C macros --- or indeed
629  any line ending with a backslash.
630  This does mean that sometimes the compiler might calculate the source line
631  wrongly when generating error messages in such cases, but there isn't any
632  other way around if multi-line macros include other chunks.
633 \end_layout
635 \begin_layout Section
636 Formatting source in LaTeX
637 \end_layout
639 \begin_layout Standard
640 The noweave replacement is a set of LaTeX macros dependant upon 
641 \emph on
642 noweb.sty
643 \emph default
644 , and which can be included with:
645 \end_layout
647 \begin_layout LyX-Code
649 \backslash
650 usepackage{newfangle.sty}
651 \end_layout
653 \begin_layout Standard
654 The LaTeX macros are shown in section 
655 \begin_inset CommandInset ref
656 LatexCommand ref
657 reference "sec:Latex-Macros"
659 \end_inset
661 , and are part of a LyX module file 
662 \begin_inset Flex CharStyle:Code
663 status collapsed
665 \begin_layout Plain Layout
666 newfangle.module
667 \end_layout
669 \end_inset
671 , which automatically includes the macros in the document pre-amble when
672  the newfangle LyX module is used.
673 \end_layout
675 \begin_layout Standard
676 Because the noweave replacement is impemented in LaTeX, there is no processing
677  stage required before running the 
678 \begin_inset Flex CharStyle:Code
679 status collapsed
681 \begin_layout Plain Layout
682 latex
683 \end_layout
685 \end_inset
687  command.
688  LaTeX may need running two or more times, so that the code chunk references
689  can be fully calculated.
690 \end_layout
692 \begin_layout Standard
693 The 
694 \begin_inset Flex CharStyle:Code
695 status collapsed
697 \begin_layout Plain Layout
698 noweb.sty
699 \end_layout
701 \end_inset
703  package is required as it is used for formatting the code chunk captions
704 \end_layout
706 \begin_layout Standard
707 The 
708 \begin_inset Flex CharStyle:Code
709 status collapsed
711 \begin_layout Plain Layout
712 listings.sty
713 \end_layout
715 \end_inset
717  package is also required, as it is used for formatting the code chunks
718  themselves.
719 \end_layout
721 \begin_layout Standard
722 The 
723 \begin_inset Flex CharStyle:Code
724 status collapsed
726 \begin_layout Plain Layout
727 xargs.sty
728 \end_layout
730 \end_inset
732  package is also required.
733 \end_layout
735 \begin_layout Chapter
736 Literate Programming with Newfangle
737 \end_layout
739 \begin_layout Standard
740 Todo.
741  Should really follow on from a part-0 explanation of what literate programming
742  is.
743 \end_layout
745 \begin_layout Chapter
746 Using Newfangle with LyX
747 \end_layout
749 \begin_layout Section
750 Setting up Lyx
751 \end_layout
753 \begin_layout Subsection
754 Installing the LyX module
755 \end_layout
757 \begin_layout Standard
758 Copy 
759 \begin_inset Flex CharStyle:Code
760 status collapsed
762 \begin_layout Plain Layout
763 newfangle.module
764 \end_layout
766 \end_inset
768  to your LyX layouts directory, which for unix users will be 
769 \begin_inset Flex CharStyle:Code
770 status collapsed
772 \begin_layout Plain Layout
773 ~/.lyx/layouts
774 \end_layout
776 \end_inset
779 \end_layout
781 \begin_layout Standard
782 You will need to reconfigure LyX by clicking Tools\SpecialChar \menuseparator
783 Reconfigure, and then
784  re-start LyX.
785 \end_layout
787 \begin_layout Subsection
788 \begin_inset CommandInset label
789 LatexCommand label
790 name "sub:Configuring-the-build"
792 \end_inset
794 Configuring the build script
795 \end_layout
797 \begin_layout Standard
798 Make sure you don't have a conversion defined for Lyx → Program
799 \end_layout
801 \begin_layout Standard
802 From the menu Tools\SpecialChar \menuseparator
803 Preferences, add a conversion from Latex(Plain) → Program
804  as:
805 \end_layout
807 \begin_layout LyX-Code
808 set -x ; newfangle -Rlyx-build $$i | 
809 \end_layout
811 \begin_layout LyX-Code
812   env LYX_b=$$b LYX_i=$$i LYX_o=$$o LYX_p=$$p LYX_r=$$r bash
813 \end_layout
815 \begin_layout Standard
816 (But don't cut-n-paste it from this document or you'll be pasting a multi-line
817  string which will break your lyx preferences file).
819 \end_layout
821 \begin_layout Standard
822 I hope that one day, LyX will set these into the environment when calling
823  the build script.
824 \end_layout
826 \begin_layout Standard
827 You may also want to consider adding options to this conversion\SpecialChar \ldots{}
829 \end_layout
831 \begin_layout LyX-Code
832 parselog=/usr/share/lyx/scripts/listerrors
833 \end_layout
835 \begin_layout Standard
836 \SpecialChar \ldots{}
837 but if you do you will lose your stderr
838 \begin_inset Foot
839 status collapsed
841 \begin_layout Plain Layout
842 There is some bash plumbing to get a copy of stderr but this footnote is
843  too small
844 \end_layout
846 \end_inset
849 \end_layout
851 \begin_layout Standard
852 Now, a shell script chunk called 
853 \begin_inset Flex CharStyle:Code
854 status collapsed
856 \begin_layout Plain Layout
857 lyx-build
858 \end_layout
860 \end_inset
862  will be extracted and run whenever you choose the Document\SpecialChar \menuseparator
863 Build Program
864  menu item.
865 \end_layout
867 \begin_layout Standard
868 The lyx-build script for this document is in section 
869 \begin_inset CommandInset ref
870 LatexCommand ref
871 reference "lyx-build-script"
873 \end_inset
875  and on a unix system will extract 
876 \begin_inset Flex CharStyle:Code
877 status collapsed
879 \begin_layout Plain Layout
880 newfangle.module
881 \end_layout
883 \end_inset
885  and the 
886 \begin_inset Flex CharStyle:Code
887 status collapsed
889 \begin_layout Plain Layout
890 newfangle
891 \end_layout
893 \end_inset
895  awk script.
896 \end_layout
898 \begin_layout Subsection
899 Preparing your Lyx document
900 \end_layout
902 \begin_layout Standard
903 It is not necessary to base your literate document on any of the original
904  LyX literate classes; so select a regular class for your document type.
905 \end_layout
907 \begin_layout Standard
908 Add the new module 
909 \emph on
910 Newfangle Literate
911 \emph default
913 \emph on
914 Listings
915 \emph default
916  and possibly also 
917 \emph on
918 Logical Markup
919 \emph default
921 \end_layout
923 \begin_layout Standard
924 In the drop-down style listbox you should notice a new style defined, called
926 \emph on
927 Chunk
928 \emph default
930 \end_layout
932 \begin_layout Standard
933 When you wish to insert a literate chunk, you enter it's plain name in the
934  Chunk style, instead of the older method that used 
935 \begin_inset Flex CharStyle:Code
936 status collapsed
938 \begin_layout Plain Layout
939 <<name>>=
940 \end_layout
942 \end_inset
944  type tags.
945  Following the chunk name, you insert a listing with: Insert\SpecialChar \menuseparator
946 Program Listing.
947 \end_layout
949 \begin_layout Standard
950 Inside the white listing box you can type (or paste using shift+ctrl+V)
951  your listing.
952  There is not need to use ctrl+enter at the end of lines as with some older
953  LyX literate techniques --- just press enter as normal.
954 \end_layout
956 \begin_layout Subsubsection
957 Customising the listing appearance
958 \end_layout
960 \begin_layout Standard
961 In the final document, the code is formatted using the 
962 \noun on
963 lstlistings
964 \noun default
965  package.
966  The chunk style doesn't just define the chunk name, but can also define
967  any other chunk options supported by the lstlistings package 
968 \begin_inset Flex CharStyle:Code
969 status collapsed
971 \begin_layout Plain Layout
973 \backslash
974 lstset
975 \end_layout
977 \end_inset
979  command.
980  In fact, what you type in the chunk style is raw latex.
981  If you want to set the chunk language without having to right-click the
982  listing, just add 
983 \begin_inset Flex CharStyle:Code
984 status collapsed
986 \begin_layout Plain Layout
987 ,lanuage=C
988 \end_layout
990 \end_inset
992  after the chunk name.
993 \end_layout
995 \begin_layout Standard
996 Of course you can do this by editing the listings box advanced properties
997  by right-clicking on the listings box, but that takes longer, and you can't
998  see at-a-glance what the advanced settings are while editing the document;
999  also advanced settings apply only to that box --- the chunk settings apply
1000  through the rest of the document
1001 \begin_inset Foot
1002 status collapsed
1004 \begin_layout Plain Layout
1005 It ought to apply only to subsequent chunks of the same name.
1006  I'll fix that later
1007 \end_layout
1009 \end_inset
1012 \begin_inset Note Note
1013 status collapsed
1015 \begin_layout Plain Layout
1016 So make sure they only apply to chunks of that name
1017 \end_layout
1019 \end_inset
1022 \end_layout
1024 \begin_layout Subsubsection
1025 Global customisations
1026 \end_layout
1028 \begin_layout Standard
1029 As 
1030 \emph on
1031 lstlistings
1032 \emph default
1033  is used to set the code chunks, it's 
1034 \begin_inset Flex CharStyle:Code
1035 status collapsed
1037 \begin_layout Plain Layout
1039 \backslash
1040 lstset
1041 \end_layout
1043 \end_inset
1045  command can be used in the pre-amble to set some document wide settings.
1046 \end_layout
1048 \begin_layout Standard
1049 If your source has many words with long sequences of capital letters, then
1051 \begin_inset Flex CharStyle:Code
1052 status collapsed
1054 \begin_layout Plain Layout
1055 columns=fullflexible
1056 \end_layout
1058 \end_inset
1060  may be a good idea, or the capital letters will get crowded.
1061  (I think lstlistings ought to use a slightly smaller font for captial letters
1062  so that they still fit).
1063 \end_layout
1065 \begin_layout Standard
1066 The font family 
1067 \begin_inset Flex CharStyle:Code
1068 status collapsed
1070 \begin_layout Plain Layout
1072 \backslash
1073 ttfamily
1074 \end_layout
1076 \end_inset
1078  looks more normal for code, but has no bold (unless luximono is used, but
1079  it doesn't work for me); so I use 
1080 \begin_inset Flex CharStyle:Code
1081 status collapsed
1083 \begin_layout Plain Layout
1085 \backslash
1086 color{darkgreen}
1087 \end_layout
1089 \end_inset
1091  for my keywords.
1092  With 
1093 \begin_inset Flex CharStyle:Code
1094 status collapsed
1096 \begin_layout Plain Layout
1098 \backslash
1099 ttfamily
1100 \end_layout
1102 \end_inset
1105 \begin_inset Flex CharStyle:Code
1106 status collapsed
1108 \begin_layout Plain Layout
1109 columns=fullflexible
1110 \end_layout
1112 \end_inset
1114  is used or the wrong letter spacing is used.
1115 \end_layout
1117 \begin_layout Standard
1118 In my LeTeX pre-amble I usually specialise my code format with:
1119 \end_layout
1121 \begin_layout Chunk
1122 document-preamble,language=tex
1123 \end_layout
1125 \begin_layout Standard
1126 \begin_inset listings
1127 inline false
1128 status open
1130 \begin_layout Plain Layout
1133 \backslash
1134 usepackage{xcolor}
1135 \end_layout
1137 \begin_layout Plain Layout
1140 \backslash
1141 definecolor{darkgreen}{rgb}{0,0.5,0}
1142 \end_layout
1144 \begin_layout Plain Layout
1147 \backslash
1148 lstset{numbers=left, stepnumber=5, numbersep=5pt, breaklines=false,
1149 \end_layout
1151 \begin_layout Plain Layout
1153   basicstyle=
1154 \backslash
1155 footnotesize
1156 \backslash
1157 ttfamily,
1158 \end_layout
1160 \begin_layout Plain Layout
1162   keywordstyle=
1163 \backslash
1164 color{darkgreen},
1165 \end_layout
1167 \begin_layout Plain Layout
1169   numberstyle=
1170 \backslash
1171 tiny,language=C,columns=fullflexible,
1172 \end_layout
1174 \begin_layout Plain Layout
1176   numberfirstline=true
1177 \end_layout
1179 \begin_layout Plain Layout
1182 \end_layout
1184 \end_inset
1187 \end_layout
1189 \begin_layout Chapter
1190 Newfangle with Makefiles
1191 \end_layout
1193 \begin_layout Standard
1194 \begin_inset Note Note
1195 status open
1197 \begin_layout Plain Layout
1198 This chapter needs revising
1199 \end_layout
1201 \end_inset
1204 \begin_inset Note Greyedout
1205 status open
1207 \begin_layout Plain Layout
1208 This chapter needs revising
1209 \end_layout
1211 \end_inset
1213 Here we describe a Makefile.inc that you can include in your own Makefiles,
1214  or glue as a recursive make to other projects.
1215 \end_layout
1217 \begin_layout Standard
1218 The Makefile.inc described here was put together for a Samba4 vfs module,
1219  but can be used in any Make project, including automake projects.
1220 \end_layout
1222 \begin_layout Section
1223 A word about makefiles formats
1224 \end_layout
1226 \begin_layout Standard
1227 Whitespace formatting is very important in a Makefile.
1228  The first character of each command line must be a TAB.
1229 \end_layout
1231 \begin_layout LyX-Code
1232 target: pre-requisite
1233 \begin_inset Newline newline
1234 \end_inset
1236    →    action
1237 \begin_inset Newline newline
1238 \end_inset
1240    →    action
1241 \end_layout
1243 \begin_layout Standard
1244 But a TAB is pretty hard to enter into most of the Lyx formats and insets
1245  I've been using.
1246  An alternative is to use a semi-colon after the pre-requisite, and a backslash
1247  at the end of each line (except the last).
1248  Then any whitespace (or none) can prefix each action.
1249 \end_layout
1251 \begin_layout LyX-Code
1252 target: pre-requisite ; 
1253 \backslash
1255 \begin_inset Newline newline
1256 \end_inset
1258 ␣␣action 
1259 \backslash
1261 \begin_inset Newline newline
1262 \end_inset
1264 ␣␣action
1265 \end_layout
1267 \begin_layout Standard
1268 This is the style that we use and it works pretty well for GNU make at least.
1269 \end_layout
1271 \begin_layout Standard
1272 We also adopt a convention that code chunks whose names beginning with ./
1273  should always be automatically extracted from the document.
1274  Code chunks whose names do not begin with ./ are for internal reference.
1275  (This doesn't prevent such chunks from being extracted directly).
1276 \end_layout
1278 \begin_layout Section
1279 Boot-strapping the extraction
1280 \end_layout
1282 \begin_layout Subsection
1283 Using a Makefile
1284 \end_layout
1286 \begin_layout Standard
1287 \begin_inset CommandInset label
1288 LatexCommand label
1289 name "sub:Bootstrap-Using-a-Makefile"
1291 \end_inset
1293 It seems convenient to have the makefile extract or update the C source
1294  files as part of it's operation.
1295  It also seems convenient to have the makefile itself extracted from this
1296  document.
1297 \end_layout
1299 \begin_layout Standard
1300 It would also be convenient to have the code to extract the makefile from
1301  this document to also be part of this document, however we have to start
1302  somewhere and this unfortunately requires us to type at least a few words
1303  by hand to start things off.
1304 \end_layout
1306 \begin_layout Standard
1307 Therefore we will have a minimal root fragment, which, when extracted, can
1308  cope with extracting the rest of the source.
1309  perhaps with this shell script, which could be called 
1310 \emph on
1311 autoboot
1312 \emph default
1314 \begin_inset Note Note
1315 status open
1317 \begin_layout Plain Layout
1318 FIX THIS CHUNK AND TEST IT
1319 \end_layout
1321 \end_inset
1324 \end_layout
1326 \begin_layout Chunk
1328 \end_layout
1330 \begin_layout Standard
1331 \begin_inset listings
1332 inline false
1333 status open
1335 \begin_layout Plain Layout
1337 #! /bin/sh
1338 \end_layout
1340 \begin_layout Plain Layout
1342 \end_layout
1344 \begin_layout Plain Layout
1346 MAKE_SRC="${1:-${NW_LYX:-../../noweb-lyx/noweb-lyx3.lyx}}"
1347 \end_layout
1349 \begin_layout Plain Layout
1351 MAKE_SRC=`dirname "$MAKE_SRC"`/`basename "$MAKE_SRC" .lyx`
1352 \end_layout
1354 \begin_layout Plain Layout
1356 NOWEB_SRC="${2:-${NOWEB_SRC:-$MAKE_SRC.lyx}}"
1357 \end_layout
1359 \begin_layout Plain Layout
1361 lyx -e latex $MAKE_SRC
1362 \end_layout
1364 \begin_layout Plain Layout
1366 \end_layout
1368 \begin_layout Plain Layout
1370 newfangle -R./Makefile.inc ${MAKE_SRC}.tex 
1371 \backslash
1373 \end_layout
1375 \begin_layout Plain Layout
1377   | sed "/NEWFANGLE_SOURCE=/s/^/#/;T;aNOWEB_SOURCE=$NEWFANGLE_SRC" 
1378 \backslash
1380 \end_layout
1382 \begin_layout Plain Layout
1384   | cpif ./Makefile.inc
1385 \end_layout
1387 \begin_layout Plain Layout
1389 \end_layout
1391 \begin_layout Plain Layout
1393 make -f ./Makefile.inc newfangle_sources
1394 \end_layout
1396 \end_inset
1399 \end_layout
1401 \begin_layout Standard
1402 The general Makefile can be invoked with 
1403 \emph on
1404 ./autoboot
1405 \emph default
1406  and can also be included into any automake file to automatically re-generate
1407  the source files.
1408 \end_layout
1410 \begin_layout Standard
1411 The 
1412 \emph on
1413 autoboot
1414 \emph default
1415  can be extracted with this command:
1416 \end_layout
1418 \begin_layout LyX-Code
1419 lyx -e latex newfangle.lyx && 
1420 \backslash
1422 \end_layout
1424 \begin_layout LyX-Code
1425 newfangle newfangle.lyx > ./autoboot
1426 \end_layout
1428 \begin_layout Standard
1429 This looks simple enough, but as mentioned, newfangle has to be had from
1430  somewhere before it can be extracted.
1431 \end_layout
1433 \begin_layout Subsection
1434 \begin_inset Note Note
1435 status collapsed
1437 \begin_layout Plain Layout
1438 MERGE THIS WITH THE SECTIONS OF THIS DOCUMENT
1439 \end_layout
1441 \end_inset
1443 \SpecialChar \ldots{}
1445 \end_layout
1447 \begin_layout Standard
1448 When the lyx-build chunk is executed, the current directory will be a temporary
1449  directory, and 
1450 \begin_inset Flex CharStyle:Code
1451 status collapsed
1453 \begin_layout Plain Layout
1454 LYX_SOURCE
1455 \end_layout
1457 \end_inset
1459  will refer to the tex file in this temporary directory.
1460  This is unfortunate as our makefile wants to run from the project directory
1461  where the Lyx file is kept.
1462 \end_layout
1464 \begin_layout Standard
1465 We can extract the project directory from $$r, and derive the probable Lyx
1466  filename from the noweb file that Lyx generated.
1467 \end_layout
1469 \begin_layout Chunk
1470 lyx-build-helper
1471 \end_layout
1473 \begin_layout Standard
1474 \begin_inset listings
1475 inline false
1476 status open
1478 \begin_layout Plain Layout
1480 PROJECT_DIR="$LYX_r"
1481 \end_layout
1483 \begin_layout Plain Layout
1485 LYX_SRC="$PROJECT_DIR/${LYX_i%.tex}.lyx"
1486 \end_layout
1488 \begin_layout Plain Layout
1490 TEX_DIR="$LYX_p"
1491 \end_layout
1493 \begin_layout Plain Layout
1495 TEX_SRC="$TEX_DIR/$LYX_i"
1496 \end_layout
1498 \end_inset
1501 \end_layout
1503 \begin_layout Standard
1504 And then we can define a lyx-build fragment similar to the autoboot fragment
1505 \end_layout
1507 \begin_layout Chunk
1508 lyx-build
1509 \end_layout
1511 \begin_layout Standard
1512 \begin_inset listings
1513 inline false
1514 status open
1516 \begin_layout Plain Layout
1518 #! /bin/sh
1519 \end_layout
1521 \begin_layout Plain Layout
1524 \backslash
1525 chunkref{lyx-build-helper}>
1526 \end_layout
1528 \begin_layout Plain Layout
1530 cd $PROJECT_DIR || exit 1
1531 \end_layout
1533 \begin_layout Plain Layout
1535 \end_layout
1537 \begin_layout Plain Layout
1539 #/usr/bin/newfangle -filter ./notanglefix-filter 
1540 \backslash
1542 \end_layout
1544 \begin_layout Plain Layout
1546 #  -R./Makefile.inc "../../noweb-lyx/noweb-lyx3.lyx" 
1547 \backslash
1549 \end_layout
1551 \begin_layout Plain Layout
1553 #  | sed '/NOWEB_SOURCE=/s/=.*/=samba4-dfs.lyx/' 
1554 \backslash
1556 \end_layout
1558 \begin_layout Plain Layout
1560 #  > ./Makefile.inc
1561 \end_layout
1563 \begin_layout Plain Layout
1566 \end_layout
1568 \begin_layout Plain Layout
1570 #make -f ./Makefile.inc newfangle_sources
1571 \end_layout
1573 \end_inset
1576 \end_layout
1578 \begin_layout Section
1579 Extracting Sources
1580 \end_layout
1582 \begin_layout Subsection
1583 Including Makefile.inc
1584 \end_layout
1586 \begin_layout Standard
1587 \begin_inset CommandInset label
1588 LatexCommand label
1589 name "sub:Keeping-extracted-files"
1591 \end_inset
1593 Makefile.inc will cope with extracting all the other source files from this
1594  document and keeping them up to date.
1596 \end_layout
1598 \begin_layout Standard
1599 It may also be included by a Makefile or Makefile.am defined in a Lyx document
1600  to automatically deal with the extraction of source files and documents.
1601 \end_layout
1603 \begin_layout Standard
1604 A makefile has two parts; variables must be defined before the targets that
1605  use them.
1606 \end_layout
1608 \begin_layout Chunk
1609 ./Makefile.inc
1610 \end_layout
1612 \begin_layout Standard
1613 \begin_inset listings
1614 inline false
1615 status open
1617 \begin_layout Plain Layout
1620 \backslash
1621 chunkref{Makefile.inc-vars}>
1622 \end_layout
1624 \begin_layout Plain Layout
1627 \backslash
1628 chunkref{Makefile.inc-targets}>
1629 \end_layout
1631 \end_inset
1634 \end_layout
1636 \begin_layout Standard
1637 We first define 
1638 \begin_inset Flex CharStyle:Code
1639 status collapsed
1641 \begin_layout Plain Layout
1642 NOWEB_SOURCE
1643 \end_layout
1645 \end_inset
1647  to hold the name of this Lyx file.
1648 \end_layout
1650 \begin_layout Chunk
1651 Makefile.inc-vars
1652 \end_layout
1654 \begin_layout Standard
1655 \begin_inset listings
1656 inline false
1657 status open
1659 \begin_layout Plain Layout
1661 LYX_SOURCE=
1662 \end_layout
1664 \begin_layout Plain Layout
1666 LITERATE_SOURCE=$(LYX_SOURCE)
1667 \end_layout
1669 \end_inset
1672 \end_layout
1674 \begin_layout Subsection
1675 Recursive use of Makefile.inc
1676 \end_layout
1678 \begin_layout Standard
1679 The makefile glue described here is used when building Samba4 vfs modules.
1680 \end_layout
1682 \begin_layout Standard
1683 If you are defining a module of an existing program you may find it easier
1684  to use a slight recursive make instead of including the makefile directly.
1685  This way there is less chance of definitions in Makefile.inc interfering
1686  with definitions in the main makefile, or with definitions in other Makefile.inc
1687  from other noweb modules.
1688 \end_layout
1690 \begin_layout Standard
1691 The glue works by adding a .PHONY target to call the recursive make, and
1692  adding this target as an additional pre-requisite to the existing targets.
1693 \end_layout
1695 \begin_layout Standard
1696 In this example, the existing build system already has a build target for
1698 \begin_inset Flex CharStyle:Code
1699 status collapsed
1701 \begin_layout Plain Layout
1702 example.o
1703 \end_layout
1705 \end_inset
1707 , so we just add another pre-requisite to that.
1708  In this case we use 
1709 \begin_inset Flex CharStyle:Code
1710 status collapsed
1712 \begin_layout Plain Layout
1713 example.tex.stamp
1714 \end_layout
1716 \end_inset
1718  as a pre-requisite, the stamp file's modified time indicating when all
1719  sources were extracted.
1720 \end_layout
1722 \begin_layout Chunk
1723 makefile-glue
1724 \end_layout
1726 \begin_layout Standard
1727 \begin_inset listings
1728 inline false
1729 status open
1731 \begin_layout Plain Layout
1733 $(example_srcdir)/example.o: $(example_srcdir)/example.tex.stamp
1734 \end_layout
1736 \end_inset
1739 \end_layout
1741 \begin_layout Standard
1742 The target for this new pre-requisite is generated by a recursive make using
1743  Makefile.inc which will make sure that the source is up to date, before
1744  it is built by the main projects makefile.
1745 \end_layout
1747 \begin_layout Chunk
1748 makefile-glue
1749 \end_layout
1751 \begin_layout Standard
1752 \begin_inset listings
1753 inline false
1754 status open
1756 \begin_layout Plain Layout
1758 $(example_srcdir)/example.tex.stamp: $(example_srcdir)/example.tex ; 
1759 \backslash
1761 \end_layout
1763 \begin_layout Plain Layout
1765         cd $(example_srcdir) && 
1766 \backslash
1768 \end_layout
1770 \begin_layout Plain Layout
1772         $(MAKE) -f Makefile.inc newfangle_sources
1773 \end_layout
1775 \end_inset
1778 \end_layout
1780 \begin_layout Standard
1781 We can do similar glue for the docs, clean and distclean targets.
1782  In this example our build system is using a double colon for these targets,
1783  so we use the same in our glue.
1784 \end_layout
1786 \begin_layout Chunk
1787 makefile-glue
1788 \end_layout
1790 \begin_layout Standard
1791 \begin_inset listings
1792 inline false
1793 status open
1795 \begin_layout Plain Layout
1797 docs:: docs_example
1798 \end_layout
1800 \begin_layout Plain Layout
1802 .PHONY: docs_example
1803 \end_layout
1805 \begin_layout Plain Layout
1807 docs_example:: ; cd $(example_srcdir) && 
1808 \backslash
1810 \end_layout
1812 \begin_layout Plain Layout
1814         $(MAKE) -f Makefile.inc docs
1815 \end_layout
1817 \begin_layout Plain Layout
1819 \end_layout
1821 \begin_layout Plain Layout
1823 clean:: clean_example
1824 \end_layout
1826 \begin_layout Plain Layout
1828 .PHONEY: clean_example
1829 \end_layout
1831 \begin_layout Plain Layout
1833 clean_example: ; cd $(example_srcdir) && 
1834 \backslash
1836 \end_layout
1838 \begin_layout Plain Layout
1840         $(MAKE) -f Makefile.inc clean
1841 \end_layout
1843 \begin_layout Plain Layout
1845 \end_layout
1847 \begin_layout Plain Layout
1849 distclean:: distclean_example
1850 \end_layout
1852 \begin_layout Plain Layout
1854 .PHONY: distclean_example
1855 \end_layout
1857 \begin_layout Plain Layout
1859 distclean_example: ; cd $(example_srcdir) && 
1860 \backslash
1862 \end_layout
1864 \begin_layout Plain Layout
1866         $(MAKE) -f Makefile.inc distclean
1867 \end_layout
1869 \end_inset
1872 \end_layout
1874 \begin_layout Standard
1875 We could do similarly for install targets to install the generated docs.
1876 \end_layout
1878 \begin_layout Subsection
1879 \begin_inset CommandInset label
1880 LatexCommand label
1881 name "sub:Converting-from-Lyx"
1883 \end_inset
1885 Converting from Lyx to LaTeX
1886 \end_layout
1888 \begin_layout Standard
1889 The first stage will always be to convert the Lyx file to a LaTeX file;
1890  this must be so not only because newfangle needs to to run on a TeX file,
1891  but also because the Lyx command 
1892 \emph on
1893 server-goto-file-line
1894 \begin_inset Foot
1895 status collapsed
1897 \begin_layout Plain Layout
1898 The Lyx command 
1899 \emph on
1900 server-goto-file-line
1901 \emph default
1902  is used to position the Lyx cursor at the compiler errors.
1903 \end_layout
1905 \end_inset
1908 \emph default
1909  insists that the line number provided is a line in the TeX file, and always
1910  reverse maps this to derive the line in the Lyx docment.
1911 \begin_inset Note Note
1912 status collapsed
1914 \begin_layout Plain Layout
1915 The tex file should probably be an automake extra dist sources or something,
1916  so that it gets produced and packaged by make dist
1917 \end_layout
1919 \end_inset
1922 \end_layout
1924 \begin_layout Standard
1925 The command [[lyx -e literate noweb-lyx.lyx]] will produce [[noweb-lyx.nw]]
1926  a tex file, so we define the noweb target to be the same as the Lyx file
1927  but with the .nw extension.
1928 \end_layout
1930 \begin_layout Chunk
1931 Makefile.inc-vars
1932 \end_layout
1934 \begin_layout Standard
1935 \begin_inset listings
1936 inline false
1937 status open
1939 \begin_layout Plain Layout
1941 TEX_SOURCE=$(LYX_SOURCE:.lyx=.tex)
1942 \end_layout
1944 \end_inset
1947 \end_layout
1949 \begin_layout Chunk
1950 Makefile.inc-targets
1951 \end_layout
1953 \begin_layout Standard
1954 \begin_inset listings
1955 inline false
1956 status open
1958 \begin_layout Plain Layout
1960 $(TEX_SOURCE): $(LYX_SOURCE) ;
1961 \backslash
1963 \end_layout
1965 \begin_layout Plain Layout
1967         lyx -e latex $<
1968 \end_layout
1970 \begin_layout Plain Layout
1972 clean_tex: ; rm -f -- $(TEX_SOURCE)
1973 \end_layout
1975 \end_inset
1978 \end_layout
1980 \begin_layout Subsection
1981 Extracting Program Source
1982 \end_layout
1984 \begin_layout Standard
1985 The program source is extracted using newfangle, which is designed to operate
1986  on a LaTeX document.
1988 \end_layout
1990 \begin_layout Chunk
1991 Makefile.inc-vars
1992 \end_layout
1994 \begin_layout Standard
1995 \begin_inset listings
1996 inline false
1997 status open
1999 \begin_layout Plain Layout
2001 NEWFANGLE_SOURCE=$(TEX_SOURCE)
2002 \end_layout
2004 \end_inset
2007 \end_layout
2009 \begin_layout Standard
2010 The Lyx document can result in any number of source documents, but not all
2011  of these will be changed each time the Lyx document is updated.
2012  We certainly don't want to update the timestamps of these files and cause
2013  the whole source tree to be recompiled just because the Lyx document was
2014  edited.
2016 \end_layout
2018 \begin_layout Standard
2019 To solve this problem we use a stamp file which is always updated each time
2020  the sources are extracted from the LaTeX document.
2021  If the stamp file is older than the LaTeX document, then we can make an
2022  attempt to re-extract the sources.
2023 \end_layout
2025 \begin_layout Chunk
2026 Makefile.inc-vars
2027 \end_layout
2029 \begin_layout Standard
2030 \begin_inset listings
2031 inline false
2032 status open
2034 \begin_layout Plain Layout
2036 NEWFANGLE_SOURCE_STAMP=$(NEWFANGLE_SOURCE).stamp
2037 \end_layout
2039 \end_inset
2042 \end_layout
2044 \begin_layout Chunk
2045 Makefile.inc-targets
2046 \end_layout
2048 \begin_layout Standard
2049 \begin_inset listings
2050 inline false
2051 status open
2053 \begin_layout Plain Layout
2055 $(NEWFANGLE_SOURCE_STAMP): $(NEWFANGLE_SOURCE) 
2056 \backslash
2058 \end_layout
2060 \begin_layout Plain Layout
2062                            $(NEWFANGLE_SOURCES) ; 
2063 \backslash
2065 \end_layout
2067 \begin_layout Plain Layout
2069         echo > $(NEWFANGLE_SOURCE_STAMP)
2070 \end_layout
2072 \begin_layout Plain Layout
2074 clean_stamp: ; rm -f $(NEWFANGLE_SOURCE_STAMP)
2075 \end_layout
2077 \begin_layout Plain Layout
2079 clean: clean_stamp
2080 \end_layout
2082 \end_inset
2085 \end_layout
2087 \begin_layout Subsection
2088 Extracting C sources
2089 \end_layout
2091 \begin_layout Standard
2092 We compute 
2093 \begin_inset Flex CharStyle:Code
2094 status collapsed
2096 \begin_layout Plain Layout
2097 NEWFANGLE_SOURCES
2098 \end_layout
2100 \end_inset
2102  to hold the names of all the C source files defined in this document.
2103  We compute this only once, by means of := in assignent.
2104  The sed deletes the any <
2105 \begin_inset space \hspace*{}
2106 \length 0in
2107 \end_inset
2109 < and >
2110 \begin_inset space \hspace*{}
2111 \length 0in
2112 \end_inset
2114 > which may surround the roots names (for noroots compatibility).
2116 \end_layout
2118 \begin_layout Standard
2119 As we use chunk names beginning with ./ to denote top level fragments that
2120  should be extracted, we filter out all fragments that do not begin with
2121  ./
2122 \end_layout
2124 \begin_layout Chunk
2125 Makefile.inc-vars
2126 \end_layout
2128 \begin_layout Standard
2129 \begin_inset listings
2130 inline false
2131 status open
2133 \begin_layout Plain Layout
2135 NEWFANGLE_PREFIX:=
2136 \backslash
2138 \backslash
2140 \end_layout
2142 \begin_layout Plain Layout
2144 NEWFANGLE_SOURCES:=$(shell 
2145 \backslash
2147 \end_layout
2149 \begin_layout Plain Layout
2151   newfangle -r $(NEWFANGLE_SOURCE) |
2152 \backslash
2154 \end_layout
2156 \begin_layout Plain Layout
2158   sed -e 's/^[<][<]//;s/[>][>]$$//;/^$(NEWFANGLE_PREFIX)/!d' 
2159 \backslash
2161 \end_layout
2163 \begin_layout Plain Layout
2165       -e 's/^$(NEWFANGLE_PREFIX)/
2166 \backslash
2168 \backslash
2169 //' )
2170 \end_layout
2172 \begin_layout Plain Layout
2175 \end_layout
2177 \end_inset
2180 \end_layout
2182 \begin_layout Chunk
2183 Makefile.inc-targets
2184 \end_layout
2186 \begin_layout Standard
2187 \begin_inset listings
2188 inline false
2189 status open
2191 \begin_layout Plain Layout
2193 .PHONY: echo_newfangle_sources
2194 \end_layout
2196 \begin_layout Plain Layout
2198 echo_newfangle_sources: ; @echo $(NEWFANGLE_SOURCES)
2199 \end_layout
2201 \end_inset
2204 \end_layout
2206 \begin_layout Standard
2207 We define a convenient target called 
2208 \begin_inset Flex CharStyle:Code
2209 status collapsed
2211 \begin_layout Plain Layout
2212 newfangle_sources
2213 \end_layout
2215 \end_inset
2217  to re-extract the source if the LaTeX file has been updated.
2218 \end_layout
2220 \begin_layout Chunk
2221 Makefile.inc-targets
2222 \end_layout
2224 \begin_layout Standard
2225 \begin_inset listings
2226 inline false
2227 status open
2229 \begin_layout Plain Layout
2231 .PHONY: newfangle_sources
2232 \end_layout
2234 \begin_layout Plain Layout
2236 newfangle_sources: $(NEWFANGLE_SOURCE_STAMP)
2237 \end_layout
2239 \end_inset
2242 \end_layout
2244 \begin_layout Standard
2245 And also a convenient target to remove extracted sources.
2246 \end_layout
2248 \begin_layout Chunk
2249 Makefile.inc-targets
2250 \end_layout
2252 \begin_layout Standard
2253 \begin_inset listings
2254 inline false
2255 status open
2257 \begin_layout Plain Layout
2259 .PHONY: clean_newfangle_sources
2260 \end_layout
2262 \begin_layout Plain Layout
2264 clean_newfangle_sources: ; 
2265 \backslash
2267 \end_layout
2269 \begin_layout Plain Layout
2271         rm -f -- $(NEWFANGLE_SOURCE_STAMP) $(NEWFANGLE_SOURCES)
2272 \end_layout
2274 \end_inset
2277 \end_layout
2279 \begin_layout Standard
2280 This 
2281 \begin_inset Flex CharStyle:Code
2282 status collapsed
2284 \begin_layout Plain Layout
2285 if_extension
2286 \end_layout
2288 \end_inset
2290  macro takes 4 arguments: the filename (1), some extensions to match (2)
2291  and a some shell command to return if the filename matches the exentions
2292  (3), or not (4).
2293 \end_layout
2295 \begin_layout Chunk
2296 Makefile.inc-vars
2297 \end_layout
2299 \begin_layout Standard
2300 \begin_inset listings
2301 inline false
2302 status open
2304 \begin_layout Plain Layout
2306 if_extension=$(if $(findstring $(suffix $(1)),$(2)),$(3),$(4))
2307 \end_layout
2309 \end_inset
2312 \end_layout
2314 \begin_layout Standard
2315 For some source files like C files, we want to output the line number and
2316  filename of the original LaTeX document from which the source came.
2317 \end_layout
2319 \begin_layout Standard
2320 To make this easier we define the file extensions for which we want to do
2321  this.
2322 \end_layout
2324 \begin_layout Chunk
2325 Makefile.inc-vars
2326 \end_layout
2328 \begin_layout Standard
2329 \begin_inset listings
2330 inline false
2331 status open
2333 \begin_layout Plain Layout
2335 C_EXTENSIONS=.c .h
2336 \end_layout
2338 \end_inset
2341 \end_layout
2343 \begin_layout Standard
2344 We can then use the if_extensions macro to define a macro which expands
2345  out to the 
2346 \begin_inset Flex CharStyle:Code
2347 status collapsed
2349 \begin_layout Plain Layout
2351 \end_layout
2353 \end_inset
2355  option if newfangle is being invoked in a C source file, so that C compile
2356  errors will refer to the line number in the Lyx document.
2358 \end_layout
2360 \begin_layout Chunk
2361 Makefile.inc-vars
2362 \end_layout
2364 \begin_layout Standard
2365 \begin_inset listings
2366 inline false
2367 status open
2369 \begin_layout Plain Layout
2371 TABS=8
2372 \end_layout
2374 \begin_layout Plain Layout
2376 nf_line=-L -T$(TABS)
2377 \end_layout
2379 \begin_layout Plain Layout
2381 newfangle=newfangle 
2382 \backslash
2384 \end_layout
2386 \begin_layout Plain Layout
2388   $(call if_extension,$(2),$(C_EXTENSIONS),$(nf_line)) 
2389 \backslash
2391 \end_layout
2393 \begin_layout Plain Layout
2395     -R"$(2)" $(1)
2396 \end_layout
2398 \end_inset
2401 \end_layout
2403 \begin_layout Standard
2404 We can use a similar trick to define an 
2405 \emph on
2406 indent
2407 \emph default
2408  macro which takes just the filename as an argument and can return a pipeline
2409  stage calling the indent command.
2410  Indent can be turned off with 
2411 \begin_inset Flex CharStyle:Code
2412 status collapsed
2414 \begin_layout Plain Layout
2415 make newfangle_sources indent=
2416 \end_layout
2418 \end_inset
2421 \end_layout
2423 \begin_layout Chunk
2424 Makefile.inc-vars
2425 \end_layout
2427 \begin_layout Standard
2428 \begin_inset listings
2429 inline false
2430 status open
2432 \begin_layout Plain Layout
2434 indent_options=-npro -kr -i8 -ts8 -sob -l80 -ss -ncs
2435 \end_layout
2437 \begin_layout Plain Layout
2439 indent=$(call if_extension,$(1),$(C_EXTENSIONS),
2440 \backslash
2442 \end_layout
2444 \begin_layout Plain Layout
2446               | indent $(indent_options))
2447 \end_layout
2449 \end_inset
2452 \end_layout
2454 \begin_layout Standard
2455 We now define the pattern for extracting a file.
2456  The files are written using noweb's 
2457 \emph on
2458 cpif
2459 \begin_inset Foot
2460 status collapsed
2462 \begin_layout Plain Layout
2464 \emph on
2465 So you still need noweb installed in order to use cpif
2466 \end_layout
2468 \end_inset
2471 \begin_inset Note Note
2472 status collapsed
2474 \begin_layout Plain Layout
2476 \emph on
2477 Write an awk version
2478 \end_layout
2480 \end_inset
2483 \emph default
2484  so that the file timestamp will not be touched if the contents haven't
2485  changed.
2486  This avoids the need to rebuild the entire project because of a typographical
2487  change in the documentation, or if only a few C source files have changed.
2488 \end_layout
2490 \begin_layout Chunk
2491 Makefile.inc-vars
2492 \end_layout
2494 \begin_layout Standard
2495 \begin_inset listings
2496 inline false
2497 status open
2499 \begin_layout Plain Layout
2501 newfangle_extract=@mkdir -p $(dir $(1)) && 
2502 \backslash
2504 \end_layout
2506 \begin_layout Plain Layout
2508   $(call newfangle,$(2),$(1)) > "$(1).tmp" && 
2509 \backslash
2511 \end_layout
2513 \begin_layout Plain Layout
2515   cat "$(1).tmp" $(indent) | cpif "$(1)" 
2516 \backslash
2518 \end_layout
2520 \begin_layout Plain Layout
2522   && rm -- "$(1).tmp" || 
2523 \backslash
2525 \end_layout
2527 \begin_layout Plain Layout
2529   (echo error newfangling $(1) from $(2) ; exit 1)
2530 \end_layout
2532 \end_inset
2535 \end_layout
2537 \begin_layout Standard
2538 We define a target which will extract or update all sources.
2539  To do this we first defined a makefile template that can do this for any
2540  source file in the LaTeX document.
2541 \end_layout
2543 \begin_layout Chunk
2544 Makefile.inc-vars
2545 \end_layout
2547 \begin_layout Standard
2548 \begin_inset listings
2549 inline false
2550 status open
2552 \begin_layout Plain Layout
2554 define NEWFANGLE_template
2555 \end_layout
2557 \begin_layout Plain Layout
2559   $(1): $(2); 
2560 \backslash
2562 \end_layout
2564 \begin_layout Plain Layout
2566     $$(call newfangle_extract,$(1),$(2))
2567 \end_layout
2569 \begin_layout Plain Layout
2571   NEWFANGLE_TARGETS+=$(1)
2572 \end_layout
2574 \begin_layout Plain Layout
2576 endef
2577 \end_layout
2579 \end_inset
2582 \end_layout
2584 \begin_layout Standard
2585 We then enumerate the discovered 
2586 \begin_inset Flex CharStyle:Code
2587 status collapsed
2589 \begin_layout Plain Layout
2590 NEWTANGLE_SOURCES
2591 \end_layout
2593 \end_inset
2595  to generate a makefile rule for each one using the makefile template we
2596  defined above.
2597 \end_layout
2599 \begin_layout Chunk
2600 Makefile.inc-targets
2601 \end_layout
2603 \begin_layout Standard
2604 \begin_inset listings
2605 inline false
2606 status open
2608 \begin_layout Plain Layout
2610 $(foreach source,$(NEWFANGLE_SOURCES),
2611 \backslash
2613 \end_layout
2615 \begin_layout Plain Layout
2617   $(eval $(call NEWFANGLE_template,$(source),$(NEWFANGLE_SOURCE))) 
2618 \backslash
2620 \end_layout
2622 \begin_layout Plain Layout
2625 \end_layout
2627 \end_inset
2630 \end_layout
2632 \begin_layout Standard
2633 These will all be built with NEWFANGLE_SOURCE_STAMP.
2634 \end_layout
2636 \begin_layout Standard
2637 We also remove the generated sources on a 
2638 \emph on
2639 make distclean
2640 \emph default
2642 \end_layout
2644 \begin_layout Chunk
2645 Makefile.inc-targets
2646 \end_layout
2648 \begin_layout Standard
2649 \begin_inset listings
2650 inline false
2651 status open
2653 \begin_layout Plain Layout
2655 _distclean: clean_newfangle_sources
2656 \end_layout
2658 \end_inset
2661 \end_layout
2663 \begin_layout Subsection
2664 Extracting Documentation
2665 \end_layout
2667 \begin_layout Standard
2668 We then identify the intermediate stages of the documentation and their
2669  build and clean targets.
2670 \end_layout
2672 \begin_layout Subsubsection
2673 Running pdflatex
2674 \end_layout
2676 \begin_layout Standard
2677 We produce a pdf file from the tex file.
2678 \end_layout
2680 \begin_layout Chunk
2681 Makefile.inc-vars
2682 \end_layout
2684 \begin_layout Standard
2685 \begin_inset listings
2686 inline false
2687 status open
2689 \begin_layout Plain Layout
2691 NEWFANGLE_PDF=$(TEX_SOURCE:.tex=.pdf)
2692 \end_layout
2694 \end_inset
2697 \end_layout
2699 \begin_layout Standard
2700 We run pdflatex twice to be sure that the contents and aux files are up
2701  to date.
2702  We certainly are required to run pdflatex twice if these files do not exist!
2703 \end_layout
2705 \begin_layout Chunk
2706 Makefile.inc-targets
2707 \end_layout
2709 \begin_layout Standard
2710 \begin_inset listings
2711 inline false
2712 status open
2714 \begin_layout Plain Layout
2716 $(NEWFANGLE_PDF): $(TEX_SOURCE); pdflatex $< && pdflatex $<
2717 \end_layout
2719 \begin_layout Plain Layout
2721 clean_pdf: ; rm -f -- $(NEWFANGLE_PDF) 
2722 \backslash
2724 \end_layout
2726 \begin_layout Plain Layout
2728                       $(TEX_SOURCE:.tex=.toc) 
2729 \backslash
2731 \end_layout
2733 \begin_layout Plain Layout
2735                       $(TEX_SOURCE:.tex=.log) 
2736 \backslash
2738 \end_layout
2740 \begin_layout Plain Layout
2742                       $(TEX_SOURCE:.tex=.aux)
2743 \end_layout
2745 \end_inset
2748 \end_layout
2750 \begin_layout Subsubsection
2751 The docs as a whole
2752 \end_layout
2754 \begin_layout Standard
2755 Currently we only build pdf as a final format, but NEWFANGLE_DOCS may later
2756  hold other output formats.
2757 \end_layout
2759 \begin_layout Chunk
2760 Makefile.inc-vars
2761 \end_layout
2763 \begin_layout Standard
2764 \begin_inset listings
2765 inline false
2766 status open
2768 \begin_layout Plain Layout
2770 NEWFANGLE_DOCS=$(NEWFANGLE_PDF)
2771 \end_layout
2773 \end_inset
2776 \end_layout
2778 \begin_layout Standard
2779 We also define newfangle_docs as a convenient phony target<
2780 \end_layout
2782 \begin_layout Chunk
2783 Makefile.inc-targets
2784 \end_layout
2786 \begin_layout Standard
2787 \begin_inset listings
2788 inline false
2789 status open
2791 \begin_layout Plain Layout
2793 .PHONY: newfangle_docs
2794 \end_layout
2796 \begin_layout Plain Layout
2798 newfangle_docs: $(NEWFANGLE_DOCS)
2799 \end_layout
2801 \begin_layout Plain Layout
2803 docs: newfangle_docs
2804 \end_layout
2806 \end_inset
2809 \end_layout
2811 \begin_layout Standard
2812 And define a convenient clean_noweb_docs which we add to the regular clean
2813  target
2814 \end_layout
2816 \begin_layout Chunk
2817 Makefile.inc-targets
2818 \end_layout
2820 \begin_layout Standard
2821 \begin_inset listings
2822 inline false
2823 status open
2825 \begin_layout Plain Layout
2827 .PHONEY: clean_newfangle_docs
2828 \end_layout
2830 \begin_layout Plain Layout
2832 clean_newfangle_docs: clean_tex clean_pdf
2833 \end_layout
2835 \begin_layout Plain Layout
2837 clean: clean_newfangle_docs
2838 \end_layout
2840 \begin_layout Plain Layout
2842 \end_layout
2844 \begin_layout Plain Layout
2846 distclean_newfangle_docs: clean_tex clean_newfangle_docs
2847 \end_layout
2849 \begin_layout Plain Layout
2851 distclean: clean distclean_newfangle_docs
2852 \end_layout
2854 \end_inset
2857 \end_layout
2859 \begin_layout Subsection
2860 Other helpers
2861 \end_layout
2863 \begin_layout Standard
2864 If Makefile.inc is included into Makefile, then extracted files can be updated
2865  with this command:
2866 \end_layout
2868 \begin_layout LyX-Code
2869 make newfangle_sources
2870 \end_layout
2872 \begin_layout Standard
2873 otherwise, with:
2874 \end_layout
2876 \begin_layout LyX-Code
2877 make -f Makefile.inc newfangle_sources
2878 \end_layout
2880 \begin_layout Part
2881 Source Code
2882 \end_layout
2884 \begin_layout Chapter
2885 Newfangle awk source code
2886 \end_layout
2888 \begin_layout Standard
2889 We use the copyright notice from chapter 
2890 \begin_inset CommandInset ref
2891 LatexCommand vref
2892 reference "cha:License"
2894 \end_inset
2897 \end_layout
2899 \begin_layout Chunk
2900 ./newfangle,language=awk,morestring=[b]{/},morekeywords=else
2901 \end_layout
2903 \begin_layout Standard
2904 \begin_inset listings
2905 inline false
2906 status open
2908 \begin_layout Plain Layout
2910 #! /usr/bin/awk -f
2911 \end_layout
2913 \begin_layout Plain Layout
2915 # =<
2916 \backslash
2917 chunkref{gpl3-copyright}>
2918 \end_layout
2920 \begin_layout Plain Layout
2922 \end_layout
2924 \end_inset
2927 \end_layout
2929 \begin_layout Standard
2930 We also use code from Arnold Robbins public domain getopt (1993 revision)
2931  defined in chapter 
2932 \begin_inset CommandInset ref
2933 LatexCommand ref
2934 reference "cha:getopt"
2936 \end_inset
2938 , and naturally want to attribute this appropriately.
2939 \end_layout
2941 \begin_layout Standard
2942 \begin_inset listings
2943 inline false
2944 status open
2946 \begin_layout Plain Layout
2948 \end_layout
2950 \begin_layout Plain Layout
2952 # NOTE: Arnold Robbins public domain getopt for awk is also used:
2953 \end_layout
2955 \begin_layout Plain Layout
2958 \backslash
2959 chunkref{getopt.awk-header}>
2960 \end_layout
2962 \begin_layout Plain Layout
2964 \end_layout
2966 \begin_layout Plain Layout
2969 \backslash
2970 chunkref{getopt.awk-getopt()}>
2971 \end_layout
2973 \begin_layout Plain Layout
2975 \end_layout
2977 \end_inset
2980 \end_layout
2982 \begin_layout Standard
2983 And include the following chunks
2984 \end_layout
2986 \begin_layout Chunk
2987 ./newfangle
2988 \end_layout
2990 \begin_layout Standard
2991 \begin_inset listings
2992 inline false
2993 status open
2995 \begin_layout Plain Layout
2998 \backslash
2999 chunkref{helper-functions}>
3000 \end_layout
3002 \begin_layout Plain Layout
3005 \backslash
3006 chunkref{mode-tracker}>
3007 \end_layout
3009 \begin_layout Plain Layout
3012 \backslash
3013 chunkref{parse_chunk_args}>
3014 \end_layout
3016 \begin_layout Plain Layout
3019 \backslash
3020 chunkref{chunk-storage-functions}>
3021 \end_layout
3023 \begin_layout Plain Layout
3026 \backslash
3027 chunkref{output_chunk_names()}>
3028 \end_layout
3030 \begin_layout Plain Layout
3033 \backslash
3034 chunkref{output_chunks()}>
3035 \end_layout
3037 \begin_layout Plain Layout
3040 \backslash
3041 chunkref{write_chunk()}>
3042 \end_layout
3044 \begin_layout Plain Layout
3047 \backslash
3048 chunkref{expand_chunk_args()}>
3049 \end_layout
3051 \begin_layout Plain Layout
3054 \backslash
3055 chunkref{begin}>
3056 \end_layout
3058 \begin_layout Plain Layout
3061 \backslash
3062 chunkref{recognize-chunk}>
3063 \end_layout
3065 \begin_layout Plain Layout
3068 \backslash
3069 chunkref{end}>
3070 \end_layout
3072 \end_inset
3075 \end_layout
3077 \begin_layout Section
3078 AWK tricks
3079 \end_layout
3081 \begin_layout Standard
3082 The portable way to erase an array in awk is to split the empty string,
3083  like this:
3084 \end_layout
3086 \begin_layout Chunk
3087 awk-delete-array,params=ARRAY
3088 \end_layout
3090 \begin_layout Standard
3091 \begin_inset listings
3092 inline false
3093 status open
3095 \begin_layout Plain Layout
3097 split("", ${ARRAY});
3098 \end_layout
3100 \end_inset
3103 \end_layout
3105 \begin_layout Chunk
3106 dump-array,params=ARRAY
3107 \end_layout
3109 \begin_layout Standard
3110 \begin_inset listings
3111 inline false
3112 status open
3114 \begin_layout Plain Layout
3116 print "
3117 \backslash
3118 nDump: ${ARRAY}
3119 \backslash
3120 n--------
3121 \backslash
3122 n" > "/dev/stderr";
3123 \end_layout
3125 \begin_layout Plain Layout
3127 for (_x in ${ARRAY}) {
3128 \end_layout
3130 \begin_layout Plain Layout
3132   print _x "=" ${ARRAY}[_x] "
3133 \backslash
3134 n" > "/dev/stderr";
3135 \end_layout
3137 \begin_layout Plain Layout
3140 \end_layout
3142 \begin_layout Plain Layout
3144 print "========
3145 \backslash
3146 n" > "/dev/stderr";
3147 \end_layout
3149 \end_inset
3152 \end_layout
3154 \begin_layout Chunk
3155 ,params=
3156 \end_layout
3158 \begin_layout Section
3159 Catching errors
3160 \end_layout
3162 \begin_layout Standard
3163 Fatal errors are issued with the error function:
3164 \end_layout
3166 \begin_layout Chunk
3167 error(),append=helper-functions
3168 \end_layout
3170 \begin_layout Standard
3171 \begin_inset listings
3172 inline false
3173 status open
3175 \begin_layout Plain Layout
3177 function error(message)
3178 \end_layout
3180 \begin_layout Plain Layout
3183 \end_layout
3185 \begin_layout Plain Layout
3187   print "ERROR: " FILENAME ":" FNR " " message > "/dev/stderr";
3188 \end_layout
3190 \begin_layout Plain Layout
3192   exit 1;
3193 \end_layout
3195 \begin_layout Plain Layout
3198 \end_layout
3200 \end_inset
3203 \end_layout
3205 \begin_layout Standard
3206 \begin_inset listings
3207 inline false
3208 status open
3210 \begin_layout Plain Layout
3212 function warning(message)
3213 \end_layout
3215 \begin_layout Plain Layout
3218 \end_layout
3220 \begin_layout Plain Layout
3222   print "WARNING: " FILENAME ":" FNR " " message > "/dev/stderr";
3223 \end_layout
3225 \begin_layout Plain Layout
3227   warnings++;
3228 \end_layout
3230 \begin_layout Plain Layout
3233 \end_layout
3235 \end_inset
3238 \end_layout
3240 \begin_layout Chapter
3241 lstlistings
3242 \end_layout
3244 \begin_layout Standard
3245 LaTeX arguments to lstlistings macros are a comma seperated list of key-value
3246  pairs.
3247  Values containing commas are enclosed in 
3248 \begin_inset Flex CharStyle:Code
3249 status collapsed
3251 \begin_layout Plain Layout
3253 \end_layout
3255 \end_inset
3257  braces 
3258 \begin_inset Flex CharStyle:Code
3259 status collapsed
3261 \begin_layout Plain Layout
3263 \end_layout
3265 \end_inset
3267 , which is to be expected for LaTeX.
3268 \end_layout
3270 \begin_layout Standard
3271 A sample expressions is:
3272 \end_layout
3274 \begin_layout LyX-Code
3275 name=thomas, params={a, b}, something, something-else
3276 \end_layout
3278 \begin_layout Standard
3279 but we see that this is just a simpler form of this expression:
3280 \end_layout
3282 \begin_layout LyX-Code
3283 name=freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3284 \end_layout
3286 \begin_layout Standard
3287 We may consider that we need a function that can parse such LaTeX expressions
3288  and assign the values to an 
3289 \noun on
3291 \noun default
3292  associated array, perhaps using a recursive parser into a multi-dimensional
3293  hash
3294 \begin_inset Foot
3295 status collapsed
3297 \begin_layout Plain Layout
3298 as AWK doesn't have nested-hash support
3299 \end_layout
3301 \end_inset
3303 , resulting in:
3304 \end_layout
3306 \begin_layout Standard
3307 \begin_inset Tabular
3308 <lyxtabular version="3" rows="6" columns="2">
3309 <features>
3310 <column alignment="left" valignment="top" width="0">
3311 <column alignment="left" valignment="top" width="0">
3312 <row>
3313 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3314 \begin_inset Text
3316 \begin_layout Plain Layout
3318 \end_layout
3320 \end_inset
3321 </cell>
3322 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3323 \begin_inset Text
3325 \begin_layout Plain Layout
3326 value
3327 \end_layout
3329 \end_inset
3330 </cell>
3331 </row>
3332 <row>
3333 <cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
3334 \begin_inset Text
3336 \begin_layout Plain Layout
3337 a[name]
3338 \end_layout
3340 \end_inset
3341 </cell>
3342 <cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3343 \begin_inset Text
3345 \begin_layout Plain Layout
3346 freddie
3347 \end_layout
3349 \end_inset
3350 </cell>
3351 </row>
3352 <row>
3353 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3354 \begin_inset Text
3356 \begin_layout Plain Layout
3357 a[foo, bar]
3358 \end_layout
3360 \end_inset
3361 </cell>
3362 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3363 \begin_inset Text
3365 \begin_layout Plain Layout
3367 \end_layout
3369 \end_inset
3370 </cell>
3371 </row>
3372 <row>
3373 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3374 \begin_inset Text
3376 \begin_layout Plain Layout
3377 a[foo, quux, quirk]
3378 \end_layout
3380 \end_inset
3381 </cell>
3382 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3383 \begin_inset Text
3385 \begin_layout Plain Layout
3387 \end_layout
3389 \end_inset
3390 </cell>
3391 </row>
3392 <row>
3393 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3394 \begin_inset Text
3396 \begin_layout Plain Layout
3397 a[foo, quux, a]
3398 \end_layout
3400 \end_inset
3401 </cell>
3402 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3403 \begin_inset Text
3405 \begin_layout Plain Layout
3406 fleeg
3407 \end_layout
3409 \end_inset
3410 </cell>
3411 </row>
3412 <row>
3413 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3414 \begin_inset Text
3416 \begin_layout Plain Layout
3417 a[etc]
3418 \end_layout
3420 \end_inset
3421 </cell>
3422 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3423 \begin_inset Text
3425 \begin_layout Plain Layout
3427 \end_layout
3429 \end_inset
3430 </cell>
3431 </row>
3432 </lyxtabular>
3434 \end_inset
3437 \end_layout
3439 \begin_layout Standard
3440 Oon reflection it seems that sometimes such nesting is not desirable, as
3441  the braces are also used to delimit values that contain commas --- we may
3442  consider that
3443 \end_layout
3445 \begin_layout LyX-Code
3446 name={williamson, freddie}
3447 \end_layout
3449 \begin_layout Standard
3450 should assign 
3451 \begin_inset Flex CharStyle:Code
3452 status collapsed
3454 \begin_layout Plain Layout
3455 williamson, freddie
3456 \end_layout
3458 \end_inset
3460  to 
3461 \begin_inset Flex CharStyle:Code
3462 status collapsed
3464 \begin_layout Plain Layout
3465 name
3466 \end_layout
3468 \end_inset
3471 \end_layout
3473 \begin_layout Standard
3474 In fact we are not so interested in the detail so as to be bothered by this,
3475  which turns out to be a good thing for two reasons.
3476  Firstly LaTeX has a malleable parser with no strict syntax, and secondly
3477  whether or not 
3478 \begin_inset Flex CharStyle:Code
3479 status collapsed
3481 \begin_layout Plain Layout
3482 williamson
3483 \end_layout
3485 \end_inset
3487  and 
3488 \begin_inset Flex CharStyle:Code
3489 status collapsed
3491 \begin_layout Plain Layout
3492 freddie
3493 \end_layout
3495 \end_inset
3497  should count as two items will be context dependant anyway.
3498 \end_layout
3500 \begin_layout Standard
3501 We need to parse this latex for only one reason; which is that we are extending
3502  lstlistings to add some additional arguments which will be used to express
3503  chunk parameters and other chunk options.
3504 \end_layout
3506 \begin_layout Section
3507 Additional lstlstings parameters
3508 \end_layout
3510 \begin_layout Standard
3511 Further on we define a 
3512 \begin_inset Flex CharStyle:Code
3513 status collapsed
3515 \begin_layout Plain Layout
3517 \backslash
3518 Chunk
3519 \end_layout
3521 \end_inset
3523  LaTeX macro whose arguments will consist of a the chunk name, optionally
3524  followed by a comma and then a comma separated list of arguments.
3525  In fact we will just need to prefix 
3526 \begin_inset Flex CharStyle:Code
3527 status collapsed
3529 \begin_layout Plain Layout
3530 name=
3531 \end_layout
3533 \end_inset
3535  to the arguments to in order to create valid lstlistings arguments.
3537 \end_layout
3539 \begin_layout Standard
3540 There will be other arguments supported too; 
3541 \end_layout
3543 \begin_layout Description
3544 params As an extension to many literate-programming styles, newfangle permits
3545  code chunks to take parameters and thus operate somewhat like C pre-processor
3546  macros, or like C++ templates.
3547  Chunk parameters are declared with a chunk argument called 
3548 \begin_inset Flex CharStyle:Code
3549 status collapsed
3551 \begin_layout Plain Layout
3552 params
3553 \end_layout
3555 \end_inset
3557 , which holds a semi-colon separated list of parameters, like this:
3558 \end_layout
3560 \begin_layout LyX-Code
3561 achunk,language=C,params=name;address
3562 \end_layout
3564 \begin_layout Description
3565 addto a named chunk that this chunk is to be included into.
3566  This saves the effort of having to declare another listing of the named
3567  chunk merely to include this one.
3568 \end_layout
3570 \begin_layout Standard
3571 Function 
3572 \begin_inset Flex Chunkref
3573 status collapsed
3575 \begin_layout Plain Layout
3576 get_chunk_args()
3577 \end_layout
3579 \end_inset
3581  will accept two paramters, 
3582 \begin_inset Flex CharStyle:Code
3583 status collapsed
3585 \begin_layout Plain Layout
3586 text
3587 \end_layout
3589 \end_inset
3591  being the text to parse, and 
3592 \begin_inset Flex CharStyle:Code
3593 status collapsed
3595 \begin_layout Plain Layout
3596 values
3597 \end_layout
3599 \end_inset
3601  being an array to receive the parsed values as described above.
3602  The optional parameter 
3603 \begin_inset Flex CharStyle:Code
3604 status collapsed
3606 \begin_layout Plain Layout
3607 path
3608 \end_layout
3610 \end_inset
3612  is used during recursion to build up the multi-dimensional array path.
3613 \end_layout
3615 \begin_layout Chunk
3616 ./newfangle
3617 \end_layout
3619 \begin_layout Standard
3620 \begin_inset listings
3621 inline false
3622 status open
3624 \begin_layout Plain Layout
3627 \backslash
3628 chunkref{get_chunk_args()}>
3629 \end_layout
3631 \end_inset
3634 \end_layout
3636 \begin_layout Chunk
3637 get_chunk_args()
3638 \end_layout
3640 \begin_layout Standard
3641 \begin_inset listings
3642 inline false
3643 status open
3645 \begin_layout Plain Layout
3647 function get_chunk_args(text, values,
3648 \end_layout
3650 \begin_layout Plain Layout
3652   # optional parameters
3653 \end_layout
3655 \begin_layout Plain Layout
3657   path, # hierarchical precursors
3658 \end_layout
3660 \begin_layout Plain Layout
3662   # local vars
3663 \end_layout
3665 \begin_layout Plain Layout
3667   a, name)
3668 \end_layout
3670 \end_inset
3673 \end_layout
3675 \begin_layout Standard
3676 The strategy is to parse the name, and then look for a value.
3677  If the value begins with a brace 
3678 \begin_inset Flex CharStyle:Code
3679 status collapsed
3681 \begin_layout Plain Layout
3683 \end_layout
3685 \end_inset
3687 , then we recurse and consume as much of the text as necessary, returning
3688  the remaining text when we encounter a leading close-brace 
3689 \begin_inset Flex CharStyle:Code
3690 status collapsed
3692 \begin_layout Plain Layout
3694 \end_layout
3696 \end_inset
3699  This being the strategy --- and executed in a loop --- we realise that
3700  we must first look for the closing brace (perhaps preceded by white space)
3701  in order to terminate the recursion, and returning remaining text.
3702 \end_layout
3704 \begin_layout Standard
3705 \begin_inset listings
3706 inline false
3707 status open
3709 \begin_layout Plain Layout
3712 \end_layout
3714 \begin_layout Plain Layout
3716   split("", next_chunk_args);
3717 \end_layout
3719 \begin_layout Plain Layout
3721   while(length(text)) {
3722 \end_layout
3724 \begin_layout Plain Layout
3726     if (match(text, "^ *}(.*)", a)) {
3727 \end_layout
3729 \begin_layout Plain Layout
3731       return a[1];
3732 \end_layout
3734 \begin_layout Plain Layout
3736     }
3737 \end_layout
3739 \begin_layout Plain Layout
3741     =<
3742 \backslash
3743 chunkref{parse-chunk-args}>
3744 \end_layout
3746 \begin_layout Plain Layout
3748   }
3749 \end_layout
3751 \begin_layout Plain Layout
3753   return text;
3754 \end_layout
3756 \begin_layout Plain Layout
3759 \end_layout
3761 \end_inset
3764 \end_layout
3766 \begin_layout Standard
3767 \begin_inset Note Note
3768 status collapsed
3770 \begin_layout Plain Layout
3771 Use BNF package here
3772 \end_layout
3774 \end_inset
3776 We can see that the text could be inspected with this regex:
3777 \end_layout
3779 \begin_layout Chunk
3780 parse-chunk-args
3781 \end_layout
3783 \begin_layout Standard
3784 \begin_inset listings
3785 inline false
3786 status open
3788 \begin_layout Plain Layout
3790 if (! match(text, " *([^,=]*[^,= ]) *(([,=]) *(([^,}]*) *,* *(.*))|)$", a))
3792 \end_layout
3794 \begin_layout Plain Layout
3796   return text;
3797 \end_layout
3799 \begin_layout Plain Layout
3802 \end_layout
3804 \end_inset
3807 \end_layout
3809 \begin_layout Standard
3810 and that 
3811 \begin_inset Flex CharStyle:Code
3812 status collapsed
3814 \begin_layout Plain Layout
3816 \end_layout
3818 \end_inset
3820  will have the following values:
3821 \end_layout
3823 \begin_layout Standard
3824 \begin_inset Tabular
3825 <lyxtabular version="3" rows="7" columns="2">
3826 <features>
3827 <column alignment="center" valignment="top" width="0">
3828 <column alignment="left" valignment="top" width="0">
3829 <row>
3830 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3831 \begin_inset Text
3833 \begin_layout Plain Layout
3834 a[n]
3835 \end_layout
3837 \end_inset
3838 </cell>
3839 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3840 \begin_inset Text
3842 \begin_layout Plain Layout
3843 assigned text
3844 \end_layout
3846 \end_inset
3847 </cell>
3848 </row>
3849 <row>
3850 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3851 \begin_inset Text
3853 \begin_layout Plain Layout
3855 \end_layout
3857 \end_inset
3858 </cell>
3859 <cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3860 \begin_inset Text
3862 \begin_layout Plain Layout
3863 freddie
3864 \end_layout
3866 \end_inset
3867 </cell>
3868 </row>
3869 <row>
3870 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3871 \begin_inset Text
3873 \begin_layout Plain Layout
3875 \end_layout
3877 \end_inset
3878 </cell>
3879 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3880 \begin_inset Text
3882 \begin_layout Plain Layout
3883 =freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3884 \end_layout
3886 \end_inset
3887 </cell>
3888 </row>
3889 <row>
3890 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3891 \begin_inset Text
3893 \begin_layout Plain Layout
3895 \end_layout
3897 \end_inset
3898 </cell>
3899 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3900 \begin_inset Text
3902 \begin_layout Plain Layout
3904 \end_layout
3906 \end_inset
3907 </cell>
3908 </row>
3909 <row>
3910 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3911 \begin_inset Text
3913 \begin_layout Plain Layout
3915 \end_layout
3917 \end_inset
3918 </cell>
3919 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3920 \begin_inset Text
3922 \begin_layout Plain Layout
3923 freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3924 \end_layout
3926 \end_inset
3927 </cell>
3928 </row>
3929 <row>
3930 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3931 \begin_inset Text
3933 \begin_layout Plain Layout
3935 \end_layout
3937 \end_inset
3938 </cell>
3939 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3940 \begin_inset Text
3942 \begin_layout Plain Layout
3943 freddie
3944 \end_layout
3946 \end_inset
3947 </cell>
3948 </row>
3949 <row>
3950 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3951 \begin_inset Text
3953 \begin_layout Plain Layout
3955 \end_layout
3957 \end_inset
3958 </cell>
3959 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3960 \begin_inset Text
3962 \begin_layout Plain Layout
3963 , foo={bar=baz, quux={quirk, a=fleeg}}, etc
3964 \end_layout
3966 \end_inset
3967 </cell>
3968 </row>
3969 </lyxtabular>
3971 \end_inset
3974 \end_layout
3976 \begin_layout Standard
3977 a[3] will be either 
3978 \begin_inset Flex CharStyle:Code
3979 status collapsed
3981 \begin_layout Plain Layout
3983 \end_layout
3985 \end_inset
3987  or 
3988 \begin_inset Flex CharStyle:Code
3989 status collapsed
3991 \begin_layout Plain Layout
3993 \end_layout
3995 \end_inset
3997  and signify whether the option named in 
3998 \begin_inset Flex CharStyle:Code
3999 status collapsed
4001 \begin_layout Plain Layout
4002 a[1]
4003 \end_layout
4005 \end_inset
4007  has a value or not (respectively).
4008 \end_layout
4010 \begin_layout Standard
4011 If the option does have a value, then if the expression 
4012 \begin_inset Flex CharStyle:Code
4013 status collapsed
4015 \begin_layout Plain Layout
4016 substr(a[4],1,1)
4017 \end_layout
4019 \end_inset
4021  returns a brace 
4022 \begin_inset Flex CharStyle:Code
4023 status collapsed
4025 \begin_layout Plain Layout
4027 \end_layout
4029 \end_inset
4031  it will signify that we need to recurse:
4032 \end_layout
4034 \begin_layout Standard
4035 \begin_inset listings
4036 inline false
4037 status open
4039 \begin_layout Plain Layout
4041 name=a[1];
4042 \end_layout
4044 \begin_layout Plain Layout
4046 if (a[3] == "=") {
4047 \end_layout
4049 \begin_layout Plain Layout
4051   if (substr(a[4],1,1) == "{") {
4052 \end_layout
4054 \begin_layout Plain Layout
4056     text = get_chunk_args(substr(a[4],2), values, path name SUBSEP);
4057 \end_layout
4059 \begin_layout Plain Layout
4061   } else {
4062 \end_layout
4064 \begin_layout Plain Layout
4066     values[path name]=a[5];
4067 \end_layout
4069 \begin_layout Plain Layout
4071     text = a[6];
4072 \end_layout
4074 \begin_layout Plain Layout
4076   }
4077 \end_layout
4079 \begin_layout Plain Layout
4081 } else {
4082 \end_layout
4084 \begin_layout Plain Layout
4086   values[path name]="";
4087 \end_layout
4089 \begin_layout Plain Layout
4091   text = a[2];
4092 \end_layout
4094 \begin_layout Plain Layout
4097 \end_layout
4099 \end_inset
4102 \end_layout
4104 \begin_layout Standard
4105 We can test this function like this:
4106 \end_layout
4108 \begin_layout Chunk
4109 gca-test.awk
4110 \end_layout
4112 \begin_layout Standard
4113 \begin_inset listings
4114 inline false
4115 status open
4117 \begin_layout Plain Layout
4120 \backslash
4121 chunkref{get_chunk_args()}>
4122 \end_layout
4124 \begin_layout Plain Layout
4126 BEGIN {
4127 \end_layout
4129 \begin_layout Plain Layout
4131   SUBSEP=".";
4132 \end_layout
4134 \begin_layout Plain Layout
4136 \end_layout
4138 \begin_layout Plain Layout
4140   print get_chunk_args("name=freddie, foo={bar=baz, quux={quirk, a=fleeg}},
4141  etc", a);
4142 \end_layout
4144 \begin_layout Plain Layout
4146   for (b in a) {
4147 \end_layout
4149 \begin_layout Plain Layout
4151     print "a[" b "] => " a[b];
4152 \end_layout
4154 \begin_layout Plain Layout
4156   }
4157 \end_layout
4159 \begin_layout Plain Layout
4162 \end_layout
4164 \end_inset
4167 \end_layout
4169 \begin_layout Standard
4170 which should give this output:
4171 \end_layout
4173 \begin_layout Chunk
4174 gca-test.awk-results
4175 \end_layout
4177 \begin_layout Standard
4178 \begin_inset listings
4179 inline false
4180 status open
4182 \begin_layout Plain Layout
4184 a[foo.quux.quirk] => 
4185 \end_layout
4187 \begin_layout Plain Layout
4189 a[foo.quux.a] => fleeg
4190 \end_layout
4192 \begin_layout Plain Layout
4194 a[foo.bar] => baz
4195 \end_layout
4197 \begin_layout Plain Layout
4199 a[etc] => 
4200 \end_layout
4202 \begin_layout Plain Layout
4204 a[name] => freddie
4205 \end_layout
4207 \end_inset
4210 \end_layout
4212 \begin_layout Section
4213 Parsing chunk arguments
4214 \end_layout
4216 \begin_layout Standard
4217 \begin_inset CommandInset label
4218 LatexCommand label
4219 name "cha:Chunk Arguments"
4221 \end_inset
4224 \end_layout
4226 \begin_layout Standard
4227 Arguments to paramterized chunks are expressed in round brackets as a comma
4228  separated list of optional arguments.
4229  For example, a chunk that is defined with:
4230 \end_layout
4232 \begin_layout LyX-Code
4234 \backslash
4235 Chunk{achunk, params=name ; address}
4236 \end_layout
4238 \begin_layout Standard
4239 could be invoked as:
4240 \end_layout
4242 \begin_layout LyX-Code
4244 \backslash
4245 chunkref{achunk}(John Jones, jones@example.com)
4246 \end_layout
4248 \begin_layout Standard
4249 An argument list may be as simple as in 
4250 \begin_inset Flex CharStyle:Code
4251 status collapsed
4253 \begin_layout Plain Layout
4255 \backslash
4256 chunkref{pull}(thing, otherthing)
4257 \end_layout
4259 \end_inset
4261  or as complex as:
4262 \end_layout
4264 \begin_layout LyX-Code
4266 \backslash
4267 chunkref{pull}(things[x, y], get_other_things(a, "(all)")) 
4268 \end_layout
4270 \begin_layout Standard
4271 --- which for all it's commas and quotes and parenthesis represents only
4272  two parameters: 
4273 \begin_inset Flex CharStyle:Code
4274 status collapsed
4276 \begin_layout Plain Layout
4277 things[x, y]
4278 \end_layout
4280 \end_inset
4282  and 
4283 \begin_inset Flex CharStyle:Code
4284 status collapsed
4286 \begin_layout Plain Layout
4287 get_other_things(a, "(all)")
4288 \end_layout
4290 \end_inset
4293 \end_layout
4295 \begin_layout Standard
4296 If we simply split parameter list on commas, then the comma in 
4297 \begin_inset Flex CharStyle:Code
4298 status collapsed
4300 \begin_layout Plain Layout
4301 things[x,y]
4302 \end_layout
4304 \end_inset
4306  would split into two seperate arguments: 
4307 \begin_inset Flex CharStyle:Code
4308 status collapsed
4310 \begin_layout Plain Layout
4311 things[x
4312 \end_layout
4314 \end_inset
4316  and 
4317 \begin_inset Flex CharStyle:Code
4318 status collapsed
4320 \begin_layout Plain Layout
4322 \end_layout
4324 \end_inset
4326 --- neither of which make sense on their own.
4327 \end_layout
4329 \begin_layout Standard
4330 One way to prevent this would be by refusing to split text between matching
4331  delimiters, such as 
4332 \begin_inset Flex CharStyle:Code
4333 status collapsed
4335 \begin_layout Plain Layout
4337 \end_layout
4339 \end_inset
4342 \begin_inset Flex CharStyle:Code
4343 status collapsed
4345 \begin_layout Plain Layout
4347 \end_layout
4349 \end_inset
4352 \begin_inset Flex CharStyle:Code
4353 status collapsed
4355 \begin_layout Plain Layout
4357 \end_layout
4359 \end_inset
4362 \begin_inset Flex CharStyle:Code
4363 status collapsed
4365 \begin_layout Plain Layout
4367 \end_layout
4369 \end_inset
4372 \begin_inset Flex CharStyle:Code
4373 status collapsed
4375 \begin_layout Plain Layout
4377 \end_layout
4379 \end_inset
4382 \begin_inset Flex CharStyle:Code
4383 status collapsed
4385 \begin_layout Plain Layout
4387 \end_layout
4389 \end_inset
4391  and most likely also 
4392 \begin_inset Flex CharStyle:Code
4393 status collapsed
4395 \begin_layout Plain Layout
4397 \end_layout
4399 \end_inset
4402 \begin_inset Flex CharStyle:Code
4403 status collapsed
4405 \begin_layout Plain Layout
4407 \end_layout
4409 \end_inset
4411  and 
4412 \begin_inset Flex CharStyle:Code
4413 status collapsed
4415 \begin_layout Plain Layout
4417 \end_layout
4419 \end_inset
4422 \begin_inset Flex CharStyle:Code
4423 status collapsed
4425 \begin_layout Plain Layout
4427 \end_layout
4429 \end_inset
4432  Of course this also makes it impossible to pass such mis-matched code fragments
4433  as parameters, but I think that it would be hard for readers to cope with
4434  authors who would pass such code unbalanced fragments as chunk parameters
4435 \begin_inset Foot
4436 status collapsed
4438 \begin_layout Plain Layout
4439 I know that I couldn't cope with users doing such things, and although the
4440  GPL3 license prevents me from actually forbidding anyone from trying, if
4441  they want it to work they'll have to write the code themselves and not
4442  expect any support from me.
4443 \end_layout
4445 \end_inset
4448 \end_layout
4450 \begin_layout Standard
4451 Unfortunately, the full set of matching delimiters may vary from language
4452  to language.
4453  In certain C++ template contexts, 
4454 \begin_inset Flex CharStyle:Code
4455 status collapsed
4457 \begin_layout Plain Layout
4459 \end_layout
4461 \end_inset
4463  and 
4464 \begin_inset Flex CharStyle:Code
4465 status collapsed
4467 \begin_layout Plain Layout
4469 \end_layout
4471 \end_inset
4473  would count as delimiters, and yet in other contexts they would not.
4474 \end_layout
4476 \begin_layout Standard
4477 This puts me in the unfortunate position of having to parse-somewhat all
4478  programming languages without knowing what they are!
4479 \end_layout
4481 \begin_layout Standard
4482 However, if this universal mode-tracking is possible, then parsing the arguments
4483  would be trivial.
4484  Such a mode tracker is described in chapter 
4485 \begin_inset CommandInset ref
4486 LatexCommand ref
4487 reference "cha:modes"
4489 \end_inset
4491  and used here with simplicity.
4492 \end_layout
4494 \begin_layout Chunk
4495 parse_chunk_args
4496 \end_layout
4498 \begin_layout Standard
4499 \begin_inset listings
4500 inline false
4501 status open
4503 \begin_layout Plain Layout
4505 function parse_chunk_args(language, text, values, mode,
4506 \end_layout
4508 \begin_layout Plain Layout
4510   # local vars
4511 \end_layout
4513 \begin_layout Plain Layout
4515   c, context, rest)
4516 \end_layout
4518 \begin_layout Plain Layout
4521 \end_layout
4523 \begin_layout Plain Layout
4525   =<
4526 \backslash
4527 chunkref{new-mode-tracker}(context, language, mode)>
4528 \end_layout
4530 \begin_layout Plain Layout
4532   rest = mode_tracker(context, text, values);
4533 \end_layout
4535 \begin_layout Plain Layout
4537   # extract values
4538 \end_layout
4540 \begin_layout Plain Layout
4542   for(c=1; c <= context[0, "values"]; c++) {
4543 \end_layout
4545 \begin_layout Plain Layout
4547     values[c] = context[0, "values", c];
4548 \end_layout
4550 \begin_layout Plain Layout
4552   }
4553 \end_layout
4555 \begin_layout Plain Layout
4557   return rest;
4558 \end_layout
4560 \begin_layout Plain Layout
4563 \end_layout
4565 \end_inset
4568 \end_layout
4570 \begin_layout Section
4571 Expanding parameters in the text
4572 \end_layout
4574 \begin_layout Standard
4575 Within the body of the chunk, the parameters are referred to with: 
4576 \begin_inset Flex CharStyle:Code
4577 status collapsed
4579 \begin_layout Plain Layout
4580 ${name}
4581 \end_layout
4583 \end_inset
4585  and 
4586 \begin_inset Flex CharStyle:Code
4587 status collapsed
4589 \begin_layout Plain Layout
4590 ${address}
4591 \end_layout
4593 \end_inset
4596  There is a strong case that a LaTeX style notation should be used, like
4598 \backslash
4599 param{name} which would be expressed in the listing as =<
4600 \backslash
4601 param{name}> and be rendered as 
4602 \begin_inset listings
4603 inline true
4604 status open
4606 \begin_layout Plain Layout
4609 \backslash
4610 param{name}>
4611 \end_layout
4613 \end_inset
4616  Such notation would make me go blind, but I do intend to adopt it
4617 \begin_inset Foot
4618 status collapsed
4620 \begin_layout Plain Layout
4621 Probably when LyX's listings inset can recognize and render it, so that
4622  I no longer have to type =<\SpecialChar \ldots{}
4624 \end_layout
4626 \end_inset
4629 \end_layout
4631 \begin_layout Standard
4632 We therefore need a function 
4633 \begin_inset Flex CharStyle:Code
4634 status collapsed
4636 \begin_layout Plain Layout
4637 expand_chunk_args
4638 \end_layout
4640 \end_inset
4642  which will take a block of text, a list of permitted parameters, and the
4643  arguments which must substitute for the parameters.
4645 \end_layout
4647 \begin_layout Standard
4648 \begin_inset CommandInset label
4649 LatexCommand label
4650 name "Here-we-split"
4652 \end_inset
4654 Here we split the text on 
4655 \begin_inset Flex CharStyle:Code
4656 status collapsed
4658 \begin_layout Plain Layout
4660 \end_layout
4662 \end_inset
4664  which means that all parts except the first will begin with a parameter
4665  name which will be terminated by 
4666 \begin_inset Flex CharStyle:Code
4667 status collapsed
4669 \begin_layout Plain Layout
4671 \end_layout
4673 \end_inset
4676  The split function will consume the literal 
4677 \begin_inset Flex CharStyle:Code
4678 status collapsed
4680 \begin_layout Plain Layout
4682 \end_layout
4684 \end_inset
4686  in each case.
4687 \end_layout
4689 \begin_layout Chunk
4690 expand_chunk_args()
4691 \end_layout
4693 \begin_layout Standard
4694 \begin_inset listings
4695 inline false
4696 status open
4698 \begin_layout Plain Layout
4700 function expand_chunk_args(text, params, args,  
4701 \end_layout
4703 \begin_layout Plain Layout
4705   p, text_array, next_text, v, t, l)
4706 \end_layout
4708 \begin_layout Plain Layout
4711 \end_layout
4713 \begin_layout Plain Layout
4715   if (split(text, text_array, "
4716 \backslash
4718 \backslash
4719 ${")) {
4720 \end_layout
4722 \begin_layout Plain Layout
4724     =<
4725 \backslash
4726 chunkref{substitute-chunk-args}>
4727 \end_layout
4729 \begin_layout Plain Layout
4731   }
4732 \end_layout
4734 \begin_layout Plain Layout
4736 \end_layout
4738 \begin_layout Plain Layout
4740   return text;
4741 \end_layout
4743 \begin_layout Plain Layout
4746 \end_layout
4748 \end_inset
4751 \end_layout
4753 \begin_layout Standard
4754 First, we produce an associative array of substitution values indexed by
4755  parameter names.
4756  This will serve as a cache, allowing us to look up the replacement values
4757  as we extract each name.
4758 \end_layout
4760 \begin_layout Chunk
4761 substitute-chunk-args
4762 \end_layout
4764 \begin_layout Standard
4765 \begin_inset listings
4766 inline false
4767 status open
4769 \begin_layout Plain Layout
4771 for(p in params) {
4772 \end_layout
4774 \begin_layout Plain Layout
4776   v[params[p]]=args[p];
4777 \end_layout
4779 \begin_layout Plain Layout
4782 \end_layout
4784 \end_inset
4787 \end_layout
4789 \begin_layout Standard
4790 We accumulate substituted text in the variable 
4791 \begin_inset Flex CharStyle:Code
4792 status collapsed
4794 \begin_layout Plain Layout
4795 text
4796 \end_layout
4798 \end_inset
4801  As the first part of the split function is the part before the delimiter
4802  --- which is 
4803 \begin_inset Flex CharStyle:Code
4804 status collapsed
4806 \begin_layout Plain Layout
4808 \end_layout
4810 \end_inset
4812  in our case --- this part will never contain a parameter reference, so
4813  we assign this directly to the result kept in 
4814 \begin_inset Flex CharStyle:Code
4815 status collapsed
4817 \begin_layout Plain Layout
4818 $text
4819 \end_layout
4821 \end_inset
4824 \begin_inset listings
4825 inline false
4826 status open
4828 \begin_layout Plain Layout
4830 text=text_array[1];
4831 \end_layout
4833 \end_inset
4836 \end_layout
4838 \begin_layout Standard
4839 We then iterate over the remaining values in the array
4840 \begin_inset Foot
4841 status collapsed
4843 \begin_layout Plain Layout
4844 I don't know why I think that it will enumerate the array in order, but
4845  it seems to work
4846 \end_layout
4848 \end_inset
4851 \begin_inset Note Note
4852 status collapsed
4854 \begin_layout Plain Layout
4855 So fix it or porve it
4856 \end_layout
4858 \end_inset
4860 , and substitute each reference for it's argument.
4861 \end_layout
4863 \begin_layout Standard
4864 \begin_inset listings
4865 inline false
4866 status open
4868 \begin_layout Plain Layout
4870 for(t=2; t in text_array; t++) {
4871 \end_layout
4873 \begin_layout Plain Layout
4875   =<
4876 \backslash
4877 chunkref{substitute-chunk-arg}>
4878 \end_layout
4880 \begin_layout Plain Layout
4883 \end_layout
4885 \end_inset
4888 \end_layout
4890 \begin_layout Standard
4891 After the split on 
4892 \begin_inset Flex CharStyle:Code
4893 status collapsed
4895 \begin_layout Plain Layout
4897 \end_layout
4899 \end_inset
4901  a valid parameter reference will consist of valid parameter name terminated
4902  by a close-brace 
4903 \begin_inset Flex CharStyle:Code
4904 status collapsed
4906 \begin_layout Plain Layout
4908 \end_layout
4910 \end_inset
4913  A valid character name begins with the underscore or a letter, and may
4914  contain letters, digits or underscores.
4915 \end_layout
4917 \begin_layout Standard
4918 A valid looking reference that is not actually the name of a parameter will
4919  be and not substituted.
4920  This is good because there is nothing to substitute anyway, and it avoids
4921  clashes when writing code for languages where ${\SpecialChar \ldots{}
4922 } is a valid construct
4923  --- such constructs will not be interfered with unless the parameter name
4924  also matches.
4925 \end_layout
4927 \begin_layout Chunk
4928 substitute-chunk-arg
4929 \end_layout
4931 \begin_layout Standard
4932 \begin_inset listings
4933 inline false
4934 status open
4936 \begin_layout Plain Layout
4938 if (match(text_array[t], "^([a-zA-Z_][a-zA-Z0-9_]*)}", l) &&
4939 \end_layout
4941 \begin_layout Plain Layout
4943     l[1] in v) 
4944 \end_layout
4946 \begin_layout Plain Layout
4949 \end_layout
4951 \begin_layout Plain Layout
4953   text = text v[l[1]] substr(text_array[t], length(l[1])+2);
4954 \end_layout
4956 \begin_layout Plain Layout
4958 } else {
4959 \end_layout
4961 \begin_layout Plain Layout
4963   text = text "${" text_array[t];
4964 \end_layout
4966 \begin_layout Plain Layout
4969 \end_layout
4971 \end_inset
4974 \end_layout
4976 \begin_layout Chapter
4977 Language Modes
4978 \end_layout
4980 \begin_layout Standard
4981 \begin_inset CommandInset label
4982 LatexCommand label
4983 name "cha:modes"
4985 \end_inset
4988 \end_layout
4990 \begin_layout Section
4991 Modes
4992 \end_layout
4994 \begin_layout Standard
4995 lstlistings and newfangle both recognize source languages, and perform some
4996  basic parsing.
4997  lstlistings can detect strings and comments within a language definition
4998  and perform suitable rendering, such as italics for comments, and visible-space
4999 s within strings.
5000 \end_layout
5002 \begin_layout Standard
5003 Newfangle similarly can recognize strings, and comments, etc, within a language,
5004  so that any chunks included with 
5005 \begin_inset Flex CharStyle:Code
5006 status collapsed
5008 \begin_layout Plain Layout
5010 \backslash
5011 chunkref
5012 \end_layout
5014 \end_inset
5016  can be suitably escape or quoted.
5017 \end_layout
5019 \begin_layout Subsection
5020 Modes to keep code together
5021 \end_layout
5023 \begin_layout Standard
5024 As an example, in the C language there are a few parse modes, affecting
5025  the interpretation of characters.
5026 \end_layout
5028 \begin_layout Standard
5029 One parse mode is the strings mode.
5030  The string mode is commenced by an un-escaped quotation mark 
5031 \begin_inset Flex CharStyle:Code
5032 status collapsed
5034 \begin_layout Plain Layout
5036 \end_layout
5038 \end_inset
5040  and terminated by the same.
5041  Within the string mode, only one additional mode can be commenced, it is
5042  the backslash mode 
5043 \begin_inset Flex CharStyle:Code
5044 status collapsed
5046 \begin_layout Plain Layout
5048 \backslash
5050 \end_layout
5052 \end_inset
5054 , which is always terminated by the folloing character.
5055 \end_layout
5057 \begin_layout Standard
5058 Other modes are 
5059 \begin_inset Flex CharStyle:Code
5060 status collapsed
5062 \begin_layout Plain Layout
5064 \end_layout
5066 \end_inset
5068  which is terminated by a 
5069 \begin_inset Flex CharStyle:Code
5070 status collapsed
5072 \begin_layout Plain Layout
5074 \end_layout
5076 \end_inset
5078  (unless it occurs in a string).
5079 \end_layout
5081 \begin_layout Standard
5082 Consider this line of C code:
5083 \end_layout
5085 \begin_layout Standard
5086 \begin_inset Formula $\mathtt{things\underbrace{[\mathtt{x,\ y}]}_{1.\ [\ mode},\ get\_other\_things\underbrace{(\mathtt{a,\overbrace{"\mathtt{(all)}"}})}_{2.\ (\ mode}^{3.\ "\ mode}}$
5087 \end_inset
5090 \end_layout
5092 \begin_layout Standard
5093 Mode nesting prevents the close parenthesis in quote mode (part 3) from
5094  terminating the parenthesis mode (part 2).
5095 \end_layout
5097 \begin_layout Standard
5098 Each language has a set of modes, the default mode being the null mode.
5099  Each mode can lead to other modes.
5100 \end_layout
5102 \begin_layout Subsection
5103 Modes to included chunks
5104 \end_layout
5106 \begin_layout Standard
5107 For instance, consider this chunk with 
5108 \begin_inset Flex CharStyle:Code
5109 status collapsed
5111 \begin_layout Plain Layout
5112 language=perl
5113 \end_layout
5115 \end_inset
5118 \end_layout
5120 \begin_layout Chunk
5121 example-perl,language=perl
5122 \end_layout
5124 \begin_layout Standard
5125 \begin_inset listings
5126 inline false
5127 status open
5129 \begin_layout Plain Layout
5131 s/"$/'/;
5132 \end_layout
5134 \end_inset
5137 \end_layout
5139 \begin_layout Standard
5140 If it were included in a chunk with 
5141 \begin_inset Flex CharStyle:Code
5142 status collapsed
5144 \begin_layout Plain Layout
5145 language=sh
5146 \end_layout
5148 \end_inset
5150 , like this:
5151 \end_layout
5153 \begin_layout Chunk
5154 example-sh,language=sh
5155 \end_layout
5157 \begin_layout Standard
5158 \begin_inset listings
5159 inline false
5160 status open
5162 \begin_layout Plain Layout
5164 perl -pe "=<
5165 \backslash
5166 chunkref{example-perl}>"
5167 \end_layout
5169 \end_inset
5172 \end_layout
5174 \begin_layout Standard
5175 newfangle would need to generate output like this if it were to work: 
5176 \end_layout
5178 \begin_layout LyX-Code
5179 perl -pe "s/
5180 \backslash
5182 \backslash
5183 $/'/;"
5184 \end_layout
5186 \begin_layout Standard
5187 See that the double quote 
5188 \begin_inset Flex CharStyle:Code
5189 status collapsed
5191 \begin_layout Plain Layout
5193 \end_layout
5195 \end_inset
5197 , and 
5198 \begin_inset Flex CharStyle:Code
5199 status collapsed
5201 \begin_layout Plain Layout
5203 \end_layout
5205 \end_inset
5207  in the regex have been quoted with a back-slash to protect them from shell
5208  interpretation.
5209 \end_layout
5211 \begin_layout Standard
5212 If that were then included in a chunk with 
5213 \begin_inset Flex CharStyle:Code
5214 status collapsed
5216 \begin_layout Plain Layout
5217 language=make
5218 \end_layout
5220 \end_inset
5222 , like this:
5223 \end_layout
5225 \begin_layout Chunk
5226 example-makefile,language=make
5227 \end_layout
5229 \begin_layout Standard
5230 \begin_inset listings
5231 inline false
5232 status open
5234 \begin_layout Plain Layout
5236 target: pre-req
5237 \end_layout
5239 \begin_layout Plain Layout
5241                 =<
5242 \backslash
5243 chunkref{example-sh}>
5244 \end_layout
5246 \end_inset
5249 \end_layout
5251 \begin_layout Standard
5252 We would need the output to look like this --- note the $$:
5253 \end_layout
5255 \begin_layout LyX-Code
5256 target: pre-req
5257 \end_layout
5259 \begin_layout LyX-Code
5260         perl -pe "s/
5261 \backslash
5263 \backslash
5264 $$/'/;"
5265 \end_layout
5267 \begin_layout Standard
5268 In order to make this work, we need to define a mode-tracker supporting
5269  each language, that can detect the various quoting modes, and provide a
5270  transformation that must be applied to any included text so that included
5271  text will be interpreted correctly after any interpolation that it may
5272  be subject to at run-time.
5273 \end_layout
5275 \begin_layout Standard
5276 For example, the sed transformation for text to be inserted into sh double-quote
5277 d strings would be something like:
5278 \end_layout
5280 \begin_layout LyX-Code
5282 \backslash
5284 \backslash
5286 \backslash
5288 \backslash
5290 \backslash
5292 \backslash
5293 /g;s/$/
5294 \backslash
5296 \backslash
5297 $/g;s/"/
5298 \backslash
5300 \backslash
5301 "/g;
5302 \end_layout
5304 \begin_layout Standard
5305 which protects 
5306 \begin_inset Flex CharStyle:Code
5307 status collapsed
5309 \begin_layout Plain Layout
5311 \backslash
5312  $ "
5313 \end_layout
5315 \end_inset
5318 \end_layout
5320 \begin_layout Standard
5321 \begin_inset Note Note
5322 status collapsed
5324 \begin_layout Plain Layout
5325 I don't think this example is true
5326 \end_layout
5328 \end_inset
5330 The mode tracker must also track nested mode-changes, as in this 
5331 \begin_inset Flex CharStyle:Code
5332 status collapsed
5334 \begin_layout Plain Layout
5336 \end_layout
5338 \end_inset
5340  example.
5341 \end_layout
5343 \begin_layout LyX-Code
5344 echo "hello `id \SpecialChar \ldots{}
5346 \end_layout
5348 \begin_layout LyX-Code
5349 \begin_inset ERT
5350 status open
5352 \begin_layout Plain Layout
5355 \backslash
5356 noindent
5357 \backslash
5358 hphantom{echo "hello `id}
5359 \end_layout
5361 \end_inset
5364 \end_layout
5366 \begin_layout Standard
5367 Any characters inserted at the point marked ↑ would need to be escaped,
5368  including 
5369 \begin_inset Flex CharStyle:Code
5370 status collapsed
5372 \begin_layout Plain Layout
5373 ` | *
5374 \end_layout
5376 \end_inset
5378  among others.
5379  First it would need escaping for the back-ticks `, and then for the double-quot
5380 es ".
5381 \end_layout
5383 \begin_layout Standard
5384 Escaping need not occur if the format and mode of the included chunk matches
5385  that of the including chunk.
5386 \end_layout
5388 \begin_layout Standard
5389 As each chunk is output a new mode tracker for that language is initialized
5390  in it's normal state.
5391  As text is output for that chunk the output mode is tracked.
5392  When a new chunk is included, a transformation appropriate to that mode
5393  is selected and pushed onto a stack of transformations.
5394  Any text to be output is first passed through this stack of transformations.
5395 \end_layout
5397 \begin_layout Standard
5398 It remains to consider if the chunk-include function should return it's
5399  generated text so that the caller can apply any transformations (and formatting
5400 ), or if it should apply the stack of transformations itself.
5401 \end_layout
5403 \begin_layout Standard
5404 Note that the transformed text should have the property of not being able
5405  to change the mode in the current chunk.
5406 \end_layout
5408 \begin_layout Standard
5409 \begin_inset Note Note
5410 status open
5412 \begin_layout Plain Layout
5413 Note chunk parameters should probably also be transformed
5414 \end_layout
5416 \end_inset
5419 \end_layout
5421 \begin_layout Section
5422 Language Mode Definitions
5423 \end_layout
5425 \begin_layout Standard
5426 All modes are stored in a single multi-dimensional hash.
5427  The first index is the language, and the second index is the mode-identifier.
5428  The third indexes are terminators, and optionally, submodes, and delimiters.
5429 \end_layout
5431 \begin_layout Standard
5432 A useful set of mode definitions for a nameless general C-type language
5433  is shown here.
5434  (Don't be confused by the double backslash escaping needed in awk.
5435  One set of escaping is for the string, and the second set of escaping is
5436  for the regex).
5438 \begin_inset Note Note
5439 status open
5441 \begin_layout Plain Layout
5442 TODO: Add =<
5443 \backslash
5444 mode{}> command which will allow us to signify that a string is regex and
5445  thus newfangle will quote it for us.
5446 \end_layout
5448 \end_inset
5451 \end_layout
5453 \begin_layout Standard
5454 Submodes are entered by the characters 
5455 \begin_inset Flex CharStyle:Code
5456 status collapsed
5458 \begin_layout Plain Layout
5460 \backslash
5462 \end_layout
5464 \end_inset
5467 \begin_inset Flex CharStyle:Code
5468 status collapsed
5470 \begin_layout Plain Layout
5472 \end_layout
5474 \end_inset
5477 \begin_inset Flex CharStyle:Code
5478 status collapsed
5480 \begin_layout Plain Layout
5482 \end_layout
5484 \end_inset
5487 \begin_inset Flex CharStyle:Code
5488 status collapsed
5490 \begin_layout Plain Layout
5492 \end_layout
5494 \end_inset
5497 \begin_inset Flex CharStyle:Code
5498 status collapsed
5500 \begin_layout Plain Layout
5502 \end_layout
5504 \end_inset
5507 \begin_inset Flex CharStyle:Code
5508 status collapsed
5510 \begin_layout Plain Layout
5512 \end_layout
5514 \end_inset
5517 \begin_inset Flex CharStyle:Code
5518 status collapsed
5520 \begin_layout Plain Layout
5522 \end_layout
5524 \end_inset
5527 \end_layout
5529 \begin_layout Chunk
5530 common-mode-definitions,params=language
5531 \end_layout
5533 \begin_layout Standard
5534 \begin_inset listings
5535 inline false
5536 status open
5538 \begin_layout Plain Layout
5540 modes[${language}, "",  "submodes" ]="
5541 \backslash
5543 \backslash
5545 \backslash
5547 \backslash
5549 \backslash
5550 "|'|{|
5551 \backslash
5553 \backslash
5555 \backslash
5557 \backslash
5559 \end_layout
5561 \end_inset
5564 \end_layout
5566 \begin_layout Standard
5567 In the default mode, a comma surrounded by un-important white space is a
5568  delimiter of language items.
5569 \end_layout
5571 \begin_layout Standard
5572 \begin_inset listings
5573 inline false
5574 status open
5576 \begin_layout Plain Layout
5578 modes[${language}, "",  "delimiters"]=" *, *";
5579 \end_layout
5581 \end_inset
5584 \end_layout
5586 \begin_layout Standard
5587 and should pass this test:
5588 \end_layout
5590 \begin_layout Standard
5591 \begin_inset Note Note
5592 status open
5594 \begin_layout Plain Layout
5595 Why do the tests run in 
5596 \begin_inset Quotes eld
5597 \end_inset
5600 \begin_inset Quotes erd
5601 \end_inset
5603  mode and not 
5604 \begin_inset Quotes eld
5605 \end_inset
5608 \begin_inset Quotes erd
5609 \end_inset
5611  mode
5612 \end_layout
5614 \end_inset
5617 \end_layout
5619 \begin_layout Chunk
5620 test:mode-definitions
5621 \end_layout
5623 \begin_layout Standard
5624 \begin_inset listings
5625 inline false
5626 status open
5628 \begin_layout Plain Layout
5630 parse_chunk_args("", "1,2,3", a, "");
5631 \end_layout
5633 \begin_layout Plain Layout
5635 if (a[1] != "1") e++;
5636 \end_layout
5638 \begin_layout Plain Layout
5640 if (a[2] != "2") e++;
5641 \end_layout
5643 \begin_layout Plain Layout
5645 if (a[3] != "3") e++;
5646 \end_layout
5648 \begin_layout Plain Layout
5650 if (length(a) != 3) e++;
5651 \end_layout
5653 \begin_layout Plain Layout
5656 \backslash
5657 chunkref{pca-test.awk:summary}>
5658 \end_layout
5660 \begin_layout Plain Layout
5662 \end_layout
5664 \begin_layout Plain Layout
5666 parse_chunk_args("", "joe, red", a, "");
5667 \end_layout
5669 \begin_layout Plain Layout
5671 if (a[1] != "joe") e++;
5672 \end_layout
5674 \begin_layout Plain Layout
5676 if (a[2] != "red") e++;
5677 \end_layout
5679 \begin_layout Plain Layout
5681 if (length(a) != 2) e++;
5682 \end_layout
5684 \begin_layout Plain Layout
5687 \backslash
5688 chunkref{pca-test.awk:summary}>
5689 \end_layout
5691 \begin_layout Plain Layout
5693 \end_layout
5695 \begin_layout Plain Layout
5697 parse_chunk_args("", "${colour}", a, "");
5698 \end_layout
5700 \begin_layout Plain Layout
5702 if (a[1] != "${colour}") e++;
5703 \end_layout
5705 \begin_layout Plain Layout
5707 if (length(a) != 1) e++;
5708 \end_layout
5710 \begin_layout Plain Layout
5713 \backslash
5714 chunkref{pca-test.awk:summary}>
5715 \end_layout
5717 \end_inset
5720 \end_layout
5722 \begin_layout Standard
5723 Nested modes are identified by a backslash, a double or single quote, various
5724  bracket styles or a /* comment.
5725 \end_layout
5727 \begin_layout Standard
5728 For each of these sub-modes modes we must also identify at a mode terminator,
5729  and any sub-modes or delimiters that may be entered
5730 \begin_inset Foot
5731 status collapsed
5733 \begin_layout Plain Layout
5734 Because we are using the sub-mode characters as the mode identifier it means
5735  we can't currently have a mode character dependant on it's context; i.e.
5737 \begin_inset Flex CharStyle:Code
5738 status collapsed
5740 \begin_layout Plain Layout
5742 \end_layout
5744 \end_inset
5746  can't behave differently when it is inside 
5747 \begin_inset Flex CharStyle:Code
5748 status collapsed
5750 \begin_layout Plain Layout
5752 \end_layout
5754 \end_inset
5757 \end_layout
5759 \end_inset
5762 \end_layout
5764 \begin_layout Subsection
5765 Backslash
5766 \end_layout
5768 \begin_layout Standard
5769 The backslash mode has no submodes or delimiters, and is terminated by any
5770  character.
5771  Note that we are not so much interested in evaluating or interpolating
5772  content as we are in delineating content.
5773  It is no matter that a double backslash (
5774 \begin_inset Flex CharStyle:Code
5775 status collapsed
5777 \begin_layout Plain Layout
5779 \backslash
5781 \backslash
5783 \end_layout
5785 \end_inset
5787 ) may represent a single backslash while a backslash-newline may represent
5788  white space, but it does matter that the newline in a backslash newline
5789  should not be able to terminate a C pre-processor statement; and so the
5790  newline will be consumed by the backslash however it is to be interpreted.
5791 \end_layout
5793 \begin_layout Chunk
5794 common-mode-definitions
5795 \end_layout
5797 \begin_layout Standard
5798 \begin_inset listings
5799 inline false
5800 status open
5802 \begin_layout Plain Layout
5804 modes[${language}, "
5805 \backslash
5807 \backslash
5808 ", "terminators"]=".";
5809 \end_layout
5811 \end_inset
5814 \end_layout
5816 \begin_layout Subsection
5817 Strings
5818 \end_layout
5820 \begin_layout Standard
5821 Common languages support two kinds of strings quoting, double quotes and
5822  single quotes.
5823 \end_layout
5825 \begin_layout Chunk
5826 mode:common-string,params=language;quote
5827 \end_layout
5829 \begin_layout Standard
5830 In a string we have one special mode, which is the backslash.
5831  This may escape an embedded quote and prevent us thinking that it should
5832  terminate the string.
5834 \end_layout
5836 \begin_layout Standard
5837 \begin_inset listings
5838 inline false
5839 status open
5841 \begin_layout Plain Layout
5843 modes[${language}, ${quote}, "submodes" ]="
5844 \backslash
5846 \backslash
5848 \backslash
5850 \backslash
5852 \end_layout
5854 \end_inset
5857 \end_layout
5859 \begin_layout Standard
5860 Otherwise, the string will be terminated by the same character that commenced
5861  it.
5862 \end_layout
5864 \begin_layout Standard
5865 \begin_inset listings
5866 inline false
5867 status open
5869 \begin_layout Plain Layout
5871 modes[${language}, ${quote}, "terminators"]=${quote};
5872 \end_layout
5874 \end_inset
5877 \end_layout
5879 \begin_layout Standard
5880 In C type languages, certain escape sequences exist in strings.
5881  We need to define mechanism to enclode any chunks included in this mode
5882  using those escape sequences.
5883  These are expressed in two parts, s meaning search, and r meaning replace.
5884 \end_layout
5886 \begin_layout Standard
5887 The first substitution is to replace a backslash with a double backslash.
5888  We do this first as other substitutions may introduce a backslash which
5889  we would not then want to escape again here.
5890 \end_layout
5892 \begin_layout Standard
5893 \begin_inset listings
5894 inline false
5895 status open
5897 \begin_layout Plain Layout
5899 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
5900 \backslash
5902 \backslash
5904 \end_layout
5906 \begin_layout Plain Layout
5908 escapes[${language}, ${quote},   escapes[${language}, ${quote}], "r"]="
5909 \backslash
5911 \backslash
5913 \backslash
5915 \backslash
5917 \end_layout
5919 \end_inset
5922 \end_layout
5924 \begin_layout Standard
5925 If the quote character occurs in the text, it should be preceded by a backslash,
5926  otherwise it would terminate the string unexpectedly.
5927 \end_layout
5929 \begin_layout Standard
5930 \begin_inset listings
5931 inline false
5932 status open
5934 \begin_layout Plain Layout
5936 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]=${quote};
5937 \end_layout
5939 \begin_layout Plain Layout
5941 escapes[${language}, ${quote},   escapes[${language}, ${quote}], "r"]="
5942 \backslash
5944 \backslash
5945 " ${quote};
5946 \end_layout
5948 \end_inset
5951 \end_layout
5953 \begin_layout Standard
5954 Any newlines in the string, must be replaced by 
5955 \begin_inset Flex CharStyle:Code
5956 status collapsed
5958 \begin_layout Plain Layout
5960 \backslash
5962 \end_layout
5964 \end_inset
5967 \end_layout
5969 \begin_layout Standard
5970 \begin_inset listings
5971 inline false
5972 status open
5974 \begin_layout Plain Layout
5976 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
5977 \backslash
5979 \end_layout
5981 \begin_layout Plain Layout
5983 escapes[${language}, ${quote},   escapes[${language}, ${quote}], "r"]="
5984 \backslash
5986 \backslash
5988 \end_layout
5990 \end_inset
5993 \end_layout
5995 \begin_layout Standard
5996 For the common modes, we define this string handling for double and single
5997  quotes.
5998 \end_layout
6000 \begin_layout Chunk
6001 common-mode-definitions,params=language
6002 \end_layout
6004 \begin_layout Standard
6005 \begin_inset listings
6006 inline false
6007 status open
6009 \begin_layout Plain Layout
6012 \backslash
6013 chunkref{mode:common-string}(${language}, "
6014 \backslash
6015 textbackslash{}"")>
6016 \end_layout
6018 \begin_layout Plain Layout
6021 \backslash
6022 chunkref{mode:common-string}(${language}, "'")>
6023 \end_layout
6025 \end_inset
6028 \end_layout
6030 \begin_layout Standard
6031 Working strings should pass this test:
6032 \end_layout
6034 \begin_layout Chunk
6035 test:mode-definitions
6036 \end_layout
6038 \begin_layout Standard
6039 \begin_inset listings
6040 inline false
6041 status open
6043 \begin_layout Plain Layout
6045 parse_chunk_args("", "say 
6046 \backslash
6047 "I said, 
6048 \backslash
6050 \backslash
6052 \backslash
6053 "Hello, how are you
6054 \backslash
6056 \backslash
6058 \backslash
6060 \backslash
6061 ", for me", a, "");
6062 \end_layout
6064 \begin_layout Plain Layout
6066 if (a[1] != "say 
6067 \backslash
6068 "I said, 
6069 \backslash
6071 \backslash
6073 \backslash
6074 "Hello, how are you
6075 \backslash
6077 \backslash
6079 \backslash
6081 \backslash
6082 "") e++;
6083 \end_layout
6085 \begin_layout Plain Layout
6087 if (a[2] != "for me") e++;
6088 \end_layout
6090 \begin_layout Plain Layout
6092 if (length(a) != 2) e++;
6093 \end_layout
6095 \begin_layout Plain Layout
6098 \backslash
6099 chunkref{pca-test.awk:summary}>
6100 \end_layout
6102 \end_inset
6105 \end_layout
6107 \begin_layout Subsection
6108 Parentheses, Braces and Brackets
6109 \end_layout
6111 \begin_layout Standard
6112 Where quotes are closed by the same character, parentheses, brackets and
6113  braces are closed by an alternate character.
6114 \end_layout
6116 \begin_layout Chunk
6117 mode:common-brackets,params=language;open;close
6118 \end_layout
6120 \begin_layout Standard
6121 \begin_inset listings
6122 inline false
6123 status open
6125 \begin_layout Plain Layout
6127 modes[${language}, ${open},  "submodes" ]="
6128 \backslash
6130 \backslash
6132 \backslash
6134 \backslash
6136 \backslash
6137 "|{|
6138 \backslash
6140 \backslash
6142 \backslash
6144 \backslash
6145 [|'|/
6146 \backslash
6148 \backslash
6150 \end_layout
6152 \begin_layout Plain Layout
6154 modes[${language}, ${open},  "delimiters"]=" *, *";
6155 \end_layout
6157 \begin_layout Plain Layout
6159 modes[${language}, ${open},  "terminators"]=${close};
6160 \end_layout
6162 \end_inset
6165 \end_layout
6167 \begin_layout Standard
6168 Note that the open is NOT a regex but the close token IS.
6170 \begin_inset Note Note
6171 status open
6173 \begin_layout Plain Layout
6174 WHen we can quote regex we won't have to put the slashes in here
6175 \end_layout
6177 \end_inset
6180 \end_layout
6182 \begin_layout Chunk
6183 common-mode-definitions,params=language
6184 \end_layout
6186 \begin_layout Standard
6187 \begin_inset listings
6188 inline false
6189 status open
6191 \begin_layout Plain Layout
6194 \backslash
6195 chunkref{mode:common-brackets}(${language}, "{", "}")>
6196 \end_layout
6198 \begin_layout Plain Layout
6201 \backslash
6202 chunkref{mode:common-brackets}(${language}, "[", "
6203 \backslash
6204 textbackslash{}
6205 \backslash
6206 textbackslash{}]")>
6207 \end_layout
6209 \begin_layout Plain Layout
6212 \backslash
6213 chunkref{mode:common-brackets}(${language}, "(", "
6214 \backslash
6215 textbackslash{}
6216 \backslash
6217 textbackslash{})")>
6218 \end_layout
6220 \end_inset
6223 \end_layout
6225 \begin_layout Subsection
6226 Customizing Standard Modes
6227 \end_layout
6229 \begin_layout Chunk
6230 mode:add-submode,params=language;mode;submode
6231 \end_layout
6233 \begin_layout Standard
6234 \begin_inset listings
6235 inline false
6236 status open
6238 \begin_layout Plain Layout
6240 modes[${language}, ${mode}, "submodes"] = modes[${language}, ${mode}, "submodes"
6241 ] "|" ${submode};
6242 \end_layout
6244 \end_inset
6247 \end_layout
6249 \begin_layout Chunk
6250 mode:add-escapes,params=language;mode;search;replace
6251 \end_layout
6253 \begin_layout Standard
6254 \begin_inset listings
6255 inline false
6256 status open
6258 \begin_layout Plain Layout
6260 escapes[${language}, ${mode}, ++escapes[${language}, ${mode}], "s"]=${search};
6261 \end_layout
6263 \begin_layout Plain Layout
6265 escapes[${language}, ${mode},   escapes[${language}, ${mode}], "r"]=${replace};
6266 \end_layout
6268 \end_inset
6271 \end_layout
6273 \begin_layout Subsection
6274 Comments
6275 \end_layout
6277 \begin_layout Standard
6278 We can define 
6279 \begin_inset Flex CharStyle:Code
6280 status collapsed
6282 \begin_layout Plain Layout
6283 /* comment */
6284 \end_layout
6286 \end_inset
6288  style comments and 
6289 \begin_inset Flex CharStyle:Code
6290 status collapsed
6292 \begin_layout Plain Layout
6293 //comment
6294 \end_layout
6296 \end_inset
6298  style comments to be added to any language:
6299 \end_layout
6301 \begin_layout Chunk
6302 mode:multi-line-comments,params=language
6303 \end_layout
6305 \begin_layout Standard
6306 \begin_inset listings
6307 inline false
6308 status open
6310 \begin_layout Plain Layout
6313 \backslash
6314 chunkref{mode:add-submode}(${language}, "", "/
6315 \backslash
6316 textbackslash{}
6317 \backslash
6318 textbackslash{}*")>
6319 \end_layout
6321 \begin_layout Plain Layout
6323 modes[${language}, "/*", "terminators"]="
6324 \backslash
6326 \backslash
6327 */";
6328 \end_layout
6330 \end_inset
6333 \end_layout
6335 \begin_layout Chunk
6336 mode:single-line-slash-comments,params=language
6337 \end_layout
6339 \begin_layout Standard
6340 \begin_inset listings
6341 inline false
6342 status open
6344 \begin_layout Plain Layout
6347 \backslash
6348 chunkref{mode:add-submode}(${language}, "", "//")>
6349 \end_layout
6351 \begin_layout Plain Layout
6353 modes[${language}, "//", "terminators"]="
6354 \backslash
6356 \end_layout
6358 \begin_layout Plain Layout
6361 \backslash
6362 chunkref{mode:add-escapes}(${language}, "//", "
6363 \backslash
6364 textbackslash{}n", "
6365 \backslash
6366 textbackslash{}n//")>
6367 \end_layout
6369 \end_inset
6372 \end_layout
6374 \begin_layout Standard
6375 We can also define 
6376 \begin_inset Flex CharStyle:Code
6377 status collapsed
6379 \begin_layout Plain Layout
6380 # comment
6381 \end_layout
6383 \end_inset
6385  style comments (as used in awk and shell scripts) in a similar manner.
6386 \end_layout
6388 \begin_layout Chunk
6389 mode:add-hash-comments,params=language
6390 \begin_inset Note Note
6391 status open
6393 \begin_layout Plain Layout
6394 I'm having to use 
6395 \backslash
6396 # for hash and 
6397 \backslash
6398 textbackslash{} for 
6399 \backslash
6400  and have hacky work-arounds in the parser for now
6401 \end_layout
6403 \end_inset
6406 \end_layout
6408 \begin_layout Standard
6409 \begin_inset listings
6410 inline false
6411 status open
6413 \begin_layout Plain Layout
6416 \backslash
6417 chunkref{mode:add-submode}(${language}, "", "
6418 \backslash
6419 #")>
6420 \end_layout
6422 \begin_layout Plain Layout
6424 modes[${language}, "#", "terminators"]="
6425 \backslash
6427 \end_layout
6429 \begin_layout Plain Layout
6432 \backslash
6433 chunkref{mode:add-escapes}(${language}, "
6434 \backslash
6435 #", "
6436 \backslash
6437 textbackslash{}n", "
6438 \backslash
6439 textbackslash{}n
6440 \backslash
6441 #")>
6442 \end_layout
6444 \end_inset
6447 \end_layout
6449 \begin_layout Standard
6450 In C, the 
6451 \begin_inset Flex CharStyle:Code
6452 status collapsed
6454 \begin_layout Plain Layout
6456 \end_layout
6458 \end_inset
6460  denotes pre-processor directives which can be multi-line 
6461 \end_layout
6463 \begin_layout Chunk
6464 mode:add-hash-defines,params=language
6465 \end_layout
6467 \begin_layout Standard
6468 \begin_inset listings
6469 inline false
6470 status open
6472 \begin_layout Plain Layout
6475 \backslash
6476 chunkref{mode:add-submode}(${language}, "", "
6477 \backslash
6478 #")>
6479 \end_layout
6481 \begin_layout Plain Layout
6483 modes[${language}, "#", "submodes" ]="
6484 \backslash
6486 \backslash
6488 \backslash
6490 \backslash
6492 \end_layout
6494 \begin_layout Plain Layout
6496 modes[${language}, "#", "terminators"]="
6497 \backslash
6499 \end_layout
6501 \begin_layout Plain Layout
6504 \backslash
6505 chunkref{mode:add-escapes}(${language}, "
6506 \backslash
6507 #", "
6508 \backslash
6509 textbackslash{}n", "
6510 \backslash
6511 textbackslash{}
6512 \backslash
6513 textbackslash{}
6514 \backslash
6515 textbackslash{}
6516 \backslash
6517 textbackslash{}
6518 \backslash
6519 textbackslash{}n")>
6520 \end_layout
6522 \end_inset
6525 \end_layout
6527 \begin_layout Standard
6528 We can add these definitions to various languages
6529 \end_layout
6531 \begin_layout Chunk
6532 mode-definitions
6533 \end_layout
6535 \begin_layout Standard
6536 \begin_inset listings
6537 inline false
6538 status open
6540 \begin_layout Plain Layout
6543 \backslash
6544 chunkref{common-mode-definitions}("")>
6545 \end_layout
6547 \begin_layout Plain Layout
6549 \end_layout
6551 \begin_layout Plain Layout
6554 \backslash
6555 chunkref{common-mode-definitions}("c")>
6556 \end_layout
6558 \begin_layout Plain Layout
6561 \backslash
6562 chunkref{mode:multi-line-comments}("c")>
6563 \end_layout
6565 \begin_layout Plain Layout
6568 \backslash
6569 chunkref{mode:single-line-slash-comments}("c")>
6570 \end_layout
6572 \begin_layout Plain Layout
6575 \backslash
6576 chunkref{mode:add-hash-defines}("c")>
6577 \end_layout
6579 \begin_layout Plain Layout
6581 \end_layout
6583 \begin_layout Plain Layout
6586 \backslash
6587 chunkref{common-mode-definitions}("awk")>
6588 \end_layout
6590 \begin_layout Plain Layout
6593 \backslash
6594 chunkref{mode:add-hash-comments}("awk")>
6595 \end_layout
6597 \end_inset
6600 \end_layout
6602 \begin_layout Standard
6603 The awk definitions should allow a comment block like this:
6604 \end_layout
6606 \begin_layout Chunk
6607 test:comment-quote,language=awk
6608 \end_layout
6610 \begin_layout Standard
6611 \begin_inset listings
6612 inline false
6613 status open
6615 \begin_layout Plain Layout
6617 # Comment: =<
6618 \backslash
6619 chunkref{test:comment-text}>
6620 \end_layout
6622 \end_inset
6625 \end_layout
6627 \begin_layout Chunk
6628 test:comment-text,language=
6629 \end_layout
6631 \begin_layout Standard
6632 \begin_inset listings
6633 inline false
6634 status open
6636 \begin_layout Plain Layout
6638 Now is the time for
6639 \end_layout
6641 \begin_layout Plain Layout
6643 the quick brown fox to bring lemonade
6644 \end_layout
6646 \begin_layout Plain Layout
6648 to the party
6649 \end_layout
6651 \end_inset
6654 \end_layout
6656 \begin_layout Standard
6657 to come out like this:
6658 \end_layout
6660 \begin_layout Chunk
6661 test:comment-quote:result
6662 \end_layout
6664 \begin_layout Standard
6665 \begin_inset listings
6666 inline false
6667 status open
6669 \begin_layout Plain Layout
6671 # Comment: Now is the time for
6672 \end_layout
6674 \begin_layout Plain Layout
6676 #the quick brown fox to bring lemonade
6677 \end_layout
6679 \begin_layout Plain Layout
6681 #to the party
6682 \end_layout
6684 \end_inset
6687 \end_layout
6689 \begin_layout Standard
6690 The C definition for such a block should have it come out like this:
6691 \end_layout
6693 \begin_layout Chunk
6694 test:comment-quote:C-result
6695 \end_layout
6697 \begin_layout Standard
6698 \begin_inset listings
6699 inline false
6700 status open
6702 \begin_layout Plain Layout
6704 # Comment: Now is the time for
6705 \backslash
6707 \end_layout
6709 \begin_layout Plain Layout
6711 the quick brown fox to bring lemonade
6712 \backslash
6714 \end_layout
6716 \begin_layout Plain Layout
6718 to the party
6719 \end_layout
6721 \end_inset
6724 \end_layout
6726 \begin_layout Section
6727 Some tests
6728 \end_layout
6730 \begin_layout Standard
6731 Also, the parser must return any spare text at the end that has not been
6732  processed due to a mode terminator being found.
6733 \end_layout
6735 \begin_layout Chunk
6736 test:mode-definitions
6737 \end_layout
6739 \begin_layout Standard
6740 \begin_inset listings
6741 inline false
6742 status open
6744 \begin_layout Plain Layout
6746 rest = parse_chunk_args("", "1, 2, 3) spare", a, "(");
6747 \end_layout
6749 \begin_layout Plain Layout
6751 if (a[1] != 1) e++;
6752 \end_layout
6754 \begin_layout Plain Layout
6756 if (a[2] != 2) e++;
6757 \end_layout
6759 \begin_layout Plain Layout
6761 if (a[3] != 3) e++;
6762 \end_layout
6764 \begin_layout Plain Layout
6766 if (length(a) != 3) e++;
6767 \end_layout
6769 \begin_layout Plain Layout
6771 if (rest != " spare") e++;
6772 \end_layout
6774 \begin_layout Plain Layout
6777 \backslash
6778 chunkref{pca-test.awk:summary}>
6779 \end_layout
6781 \end_inset
6784 \end_layout
6786 \begin_layout Standard
6787 We must also be able to parse the example given earlier.
6788 \end_layout
6790 \begin_layout Chunk
6791 test:mode-definitions
6792 \end_layout
6794 \begin_layout Standard
6795 \begin_inset listings
6796 inline false
6797 status open
6799 \begin_layout Plain Layout
6801 parse_chunk_args("", "things[x, y], get_other_things(a, 
6802 \backslash
6803 "(all)
6804 \backslash
6805 "), 99", a, "(");
6806 \end_layout
6808 \begin_layout Plain Layout
6810 if (a[1] != "things[x, y]") e++;
6811 \end_layout
6813 \begin_layout Plain Layout
6815 if (a[2] != "get_other_things(a, 
6816 \backslash
6817 "(all)
6818 \backslash
6819 ")") e++;
6820 \end_layout
6822 \begin_layout Plain Layout
6824 if (a[3] != "99") e++;
6825 \end_layout
6827 \begin_layout Plain Layout
6829 if (length(a) != 3) e++;
6830 \end_layout
6832 \begin_layout Plain Layout
6835 \backslash
6836 chunkref{pca-test.awk:summary}>
6837 \end_layout
6839 \end_inset
6842 \end_layout
6844 \begin_layout Section
6845 A non-recursive mode tracker
6846 \end_layout
6848 \begin_layout Subsection
6849 Constructor
6850 \end_layout
6852 \begin_layout Standard
6853 The mode tracker holds its state in a stack based on a hash.
6854  This function, when passed an empty hash will intialize it.
6855 \end_layout
6857 \begin_layout Chunk
6858 new_mode_tracker()
6859 \end_layout
6861 \begin_layout Standard
6862 \begin_inset listings
6863 inline false
6864 status open
6866 \begin_layout Plain Layout
6868 function new_mode_tracker(context, language, mode) {
6869 \end_layout
6871 \begin_layout Plain Layout
6873   context[""] = 0;
6874 \end_layout
6876 \begin_layout Plain Layout
6878   context[0, "language"] = language;
6879 \end_layout
6881 \begin_layout Plain Layout
6883   context[0, "mode"] = mode;
6884 \end_layout
6886 \begin_layout Plain Layout
6889 \end_layout
6891 \end_inset
6894 \end_layout
6896 \begin_layout Standard
6897 Because awk functions cannot return an array, we must create the array first
6898  and pass it in, so we have a newfangle macro to do this:
6899 \end_layout
6901 \begin_layout Chunk
6902 new-mode-tracker,params=context;language;mode
6903 \end_layout
6905 \begin_layout Standard
6906 \begin_inset listings
6907 inline false
6908 status open
6910 \begin_layout Plain Layout
6913 \backslash
6914 chunkref{awk-delete-array}(${context})>
6915 \end_layout
6917 \begin_layout Plain Layout
6919 new_mode_tracker(${context}, ${language}, ${mode});
6920 \end_layout
6922 \end_inset
6925 \end_layout
6927 \begin_layout Subsection
6928 Management
6929 \end_layout
6931 \begin_layout Standard
6932 And for tracking modes, we dispatch to a mode-tracker action based on the
6933  current language
6934 \end_layout
6936 \begin_layout Chunk
6937 mode_tracker
6938 \end_layout
6940 \begin_layout Standard
6941 \begin_inset listings
6942 inline false
6943 status open
6945 \begin_layout Plain Layout
6947 function push_mode_tracker(context, language, mode,
6948 \end_layout
6950 \begin_layout Plain Layout
6952   # local vars
6953 \end_layout
6955 \begin_layout Plain Layout
6957   top)
6958 \end_layout
6960 \begin_layout Plain Layout
6963 \end_layout
6965 \begin_layout Plain Layout
6967   if (! ("" in context)) {
6968 \end_layout
6970 \begin_layout Plain Layout
6972     =<
6973 \backslash
6974 chunkref{new-mode-tracker}(context, language, mode)>
6975 \end_layout
6977 \begin_layout Plain Layout
6979   } else {
6980 \end_layout
6982 \begin_layout Plain Layout
6984     top = context[""];
6985 \end_layout
6987 \begin_layout Plain Layout
6989     if (context[top, "language"] == language && mode=="") mode = context[top,
6990  "mode"];
6991 \end_layout
6993 \begin_layout Plain Layout
6995     top++;
6996 \end_layout
6998 \begin_layout Plain Layout
7000     context[top, "language"] = language;
7001 \end_layout
7003 \begin_layout Plain Layout
7005     context[top, "mode"] = mode;
7006 \end_layout
7008 \begin_layout Plain Layout
7010     context[""] = top;
7011 \end_layout
7013 \begin_layout Plain Layout
7015   }
7016 \end_layout
7018 \begin_layout Plain Layout
7021 \end_layout
7023 \end_inset
7026 \end_layout
7028 \begin_layout Standard
7029 \begin_inset listings
7030 inline false
7031 status open
7033 \begin_layout Plain Layout
7035 function finalize_mode_tracker(context,
7036 \end_layout
7038 \begin_layout Plain Layout
7040   # local vars
7041 \end_layout
7043 \begin_layout Plain Layout
7045   top)
7046 \end_layout
7048 \begin_layout Plain Layout
7051 \end_layout
7053 \begin_layout Plain Layout
7055   if ( ("" in context) && context[""] != 0) return 0;
7056 \end_layout
7058 \begin_layout Plain Layout
7060   return 1;
7061 \end_layout
7063 \begin_layout Plain Layout
7066 \end_layout
7068 \end_inset
7071 \end_layout
7073 \begin_layout Standard
7074 This implies that any chunk must be syntactically whole; for instance, this
7075  is fine:
7076 \end_layout
7078 \begin_layout Chunk
7079 test:whole-chunk
7080 \end_layout
7082 \begin_layout Standard
7083 \begin_inset listings
7084 inline false
7085 status open
7087 \begin_layout Plain Layout
7089 if (1) {
7090 \end_layout
7092 \begin_layout Plain Layout
7094   =<
7095 \backslash
7096 chunkref{test:say-hello}>
7097 \end_layout
7099 \begin_layout Plain Layout
7102 \end_layout
7104 \end_inset
7107 \end_layout
7109 \begin_layout Chunk
7110 test:say-hello
7111 \end_layout
7113 \begin_layout Standard
7114 \begin_inset listings
7115 inline false
7116 status open
7118 \begin_layout Plain Layout
7120 print "hello";
7121 \end_layout
7123 \end_inset
7126 \end_layout
7128 \begin_layout Standard
7129 But this is not fine; the chunk 
7130 \begin_inset Flex Chunkref
7131 status collapsed
7133 \begin_layout Plain Layout
7134 test:hidden-else
7135 \end_layout
7137 \end_inset
7139  is not properly cromulent.
7140 \end_layout
7142 \begin_layout Chunk
7143 test:partial-chunk
7144 \end_layout
7146 \begin_layout Standard
7147 \begin_inset listings
7148 inline false
7149 status open
7151 \begin_layout Plain Layout
7153 if (1) {
7154 \end_layout
7156 \begin_layout Plain Layout
7158   =<
7159 \backslash
7160 chunkref{test:hidden-else}>
7161 \end_layout
7163 \begin_layout Plain Layout
7166 \end_layout
7168 \end_inset
7171 \end_layout
7173 \begin_layout Chunk
7174 test:hidden-else
7175 \end_layout
7177 \begin_layout Standard
7178 \begin_inset listings
7179 inline false
7180 status open
7182 \begin_layout Plain Layout
7184   print "I'm fine";
7185 \end_layout
7187 \begin_layout Plain Layout
7189 } else {
7190 \end_layout
7192 \begin_layout Plain Layout
7194   print "I'm not";
7195 \end_layout
7197 \end_inset
7200 \end_layout
7202 \begin_layout Standard
7203 These tests will check for correct behaviour:
7204 \end_layout
7206 \begin_layout Chunk
7207 test:cromulence
7208 \end_layout
7210 \begin_layout Standard
7211 \begin_inset listings
7212 inline false
7213 status open
7215 \begin_layout Plain Layout
7217 echo Cromulence test
7218 \end_layout
7220 \begin_layout Plain Layout
7222 passtest ./newfangle -Rtest:whole-chunk $TEX_SRC &>/dev/null || ( echo "Whole
7223  chunk failed" && exit 1 )
7224 \end_layout
7226 \begin_layout Plain Layout
7228 failtest ./newfangle -Rtest:partial-chunk $TEX_SRC &>/dev/null || ( echo
7229  "Partial chunk failed" && exit 1 )
7230 \end_layout
7232 \end_inset
7235 \end_layout
7237 \begin_layout Subsection
7238 Tracker
7239 \end_layout
7241 \begin_layout Standard
7242 We must avoid recursion as a language construct because we intend to employ
7243  mode-tracking to track language mode of emitted code, and the code is emitted
7244  from a function which is itself recursive, so instead we implement psuedo-recur
7245 sion using our own stack based on a hash.
7246 \end_layout
7248 \begin_layout Chunk
7249 mode_tracker()
7250 \end_layout
7252 \begin_layout Standard
7253 \begin_inset listings
7254 inline false
7255 status open
7257 \begin_layout Plain Layout
7259 function mode_tracker(context, text, values, 
7260 \end_layout
7262 \begin_layout Plain Layout
7264   # optional parameters
7265 \end_layout
7267 \begin_layout Plain Layout
7269   # local vars
7270 \end_layout
7272 \begin_layout Plain Layout
7274   mode, submodes, language,
7275 \end_layout
7277 \begin_layout Plain Layout
7279   cindex, c, a, part, item, name, result, new_values, new_mode, 
7280 \end_layout
7282 \begin_layout Plain Layout
7284   delimiters, terminators)
7285 \end_layout
7287 \begin_layout Plain Layout
7290 \end_layout
7292 \end_inset
7295 \end_layout
7297 \begin_layout Standard
7298 We could be re-commencing with a valid context, so we need to setup the
7299  state according to the last context.
7300 \end_layout
7302 \begin_layout Standard
7303 \begin_inset listings
7304 inline false
7305 status open
7307 \begin_layout Plain Layout
7309   cindex = context[""] + 0;
7310 \end_layout
7312 \begin_layout Plain Layout
7314   mode = context[cindex, "mode"];
7315 \end_layout
7317 \begin_layout Plain Layout
7319   language = context[cindex, "language" ];
7320 \end_layout
7322 \end_inset
7325 \end_layout
7327 \begin_layout Standard
7328 First we construct a single large regex combining the possible sub-modes
7329  for the current mode along with the terminators for the current mode.
7330 \end_layout
7332 \begin_layout Chunk
7333 parse_chunk_args-reset-modes
7334 \end_layout
7336 \begin_layout Standard
7337 \begin_inset listings
7338 inline false
7339 status open
7341 \begin_layout Plain Layout
7343   submodes=modes[language, mode, "submodes"];
7344 \end_layout
7346 \begin_layout Plain Layout
7348 \end_layout
7350 \begin_layout Plain Layout
7352   if ((language, mode, "delimiters") in modes) {
7353 \end_layout
7355 \begin_layout Plain Layout
7357     delimiters = modes[language, mode, "delimiters"];
7358 \end_layout
7360 \begin_layout Plain Layout
7362     if (length(submodes)>0) submodes = submodes "|";
7363 \end_layout
7365 \begin_layout Plain Layout
7367     submodes=submodes delimiters;
7368 \end_layout
7370 \begin_layout Plain Layout
7372   } else delimiters="";
7373 \end_layout
7375 \begin_layout Plain Layout
7377   if ((language, mode, "terminators") in modes) {
7378 \end_layout
7380 \begin_layout Plain Layout
7382     terminators = modes[language, mode, "terminators"];
7383 \end_layout
7385 \begin_layout Plain Layout
7387     if (length(submodes)>0) submodes = submodes "|";
7388 \end_layout
7390 \begin_layout Plain Layout
7392     submodes=submodes terminators;
7393 \end_layout
7395 \begin_layout Plain Layout
7397   } else terminators="";
7398 \end_layout
7400 \end_inset
7403 \end_layout
7405 \begin_layout Standard
7406 If we don't find anything to match on --- probably because the language
7407  is not supported --- then we return the entire text without matching anything.
7408 \end_layout
7410 \begin_layout Standard
7411 \begin_inset listings
7412 inline false
7413 status open
7415 \begin_layout Plain Layout
7417   if (! length(submodes)) return text; 
7418 \end_layout
7420 \end_inset
7423 \end_layout
7425 \begin_layout Chunk
7426 mode_tracker()
7427 \end_layout
7429 \begin_layout Standard
7430 \begin_inset listings
7431 inline false
7432 status open
7434 \begin_layout Plain Layout
7437 \backslash
7438 chunkref{parse_chunk_args-reset-modes}>
7439 \end_layout
7441 \end_inset
7444 \end_layout
7446 \begin_layout Standard
7447 We then iterate the text (until there is none left) looking for sub-modes
7448  or terminators in the regex.
7449 \end_layout
7451 \begin_layout Standard
7452 \begin_inset listings
7453 inline false
7454 status open
7456 \begin_layout Plain Layout
7458   while((cindex >= 0) && length(text)) {
7459 \end_layout
7461 \begin_layout Plain Layout
7463     if (match(text, "(" submodes ")", a)) {
7464 \end_layout
7466 \end_inset
7469 \end_layout
7471 \begin_layout Standard
7472 A bug that creeps in regularly during development is bad regexes of zero
7473  length which result in an infinite loop (as no text is consumed), so I
7474  catch that right away with this test.
7475 \end_layout
7477 \begin_layout Standard
7478 \begin_inset listings
7479 inline false
7480 status open
7482 \begin_layout Plain Layout
7484       if (RLENGTH<1) {
7485 \end_layout
7487 \begin_layout Plain Layout
7489         error(sprintf("Internal error, matched zero length submode, should
7490  be impossible - likely regex computation error
7491 \backslash
7492 n" 
7493 \backslash
7495 \end_layout
7497 \begin_layout Plain Layout
7499                 "Language=%s
7500 \backslash
7501 nmode=%s
7502 \backslash
7503 nmatch=%s
7504 \backslash
7505 n", language, mode, submodes));
7506 \end_layout
7508 \begin_layout Plain Layout
7510       }
7511 \end_layout
7513 \end_inset
7516 \end_layout
7518 \begin_layout Standard
7519 \begin_inset Flex CharStyle:Code
7520 status collapsed
7522 \begin_layout Plain Layout
7523 part
7524 \end_layout
7526 \end_inset
7528  is defined as the text up to the sub-mode or terminator, and this is appended
7529  to 
7530 \begin_inset Flex CharStyle:Code
7531 status collapsed
7533 \begin_layout Plain Layout
7534 item
7535 \end_layout
7537 \end_inset
7539  --- which is the current text being gathered.
7540  If a mode has a delimiter, then item is reset each time a delimiter is
7541  found.
7542 \end_layout
7544 \begin_layout Standard
7545 \begin_inset Formula $\mathtt{\overbrace{"\overbrace{hello}^{item},\ \overbrace{there}^{item}"}^{item},\ \overbrace{he\ said.}^{item}}$
7546 \end_inset
7549 \end_layout
7551 \begin_layout Standard
7552 \begin_inset listings
7553 inline false
7554 status open
7556 \begin_layout Plain Layout
7558       part = substr(text, 1, RSTART -1);
7559 \end_layout
7561 \begin_layout Plain Layout
7563       item = item part;
7564 \end_layout
7566 \end_inset
7569 \end_layout
7571 \begin_layout Standard
7572 We must now determine what was matched.
7573  If it was a terminator, then we must restore the previous mode.
7574 \end_layout
7576 \begin_layout Standard
7577 \begin_inset listings
7578 inline false
7579 status open
7581 \begin_layout Plain Layout
7583       if (match(a[1], "^" terminators "$")) {
7584 \end_layout
7586 \begin_layout Plain Layout
7588 #printf("%2d EXIT  MODE [%s] by [%s] [%s]
7589 \backslash
7590 n", cindex, mode, a[1], text) > "/dev/stderr"
7591 \end_layout
7593 \begin_layout Plain Layout
7595         context[cindex, "values", ++context[cindex, "values"]] = item;
7596 \end_layout
7598 \begin_layout Plain Layout
7600         delete context[cindex];
7601 \end_layout
7603 \begin_layout Plain Layout
7605         context[""] = --cindex;
7606 \end_layout
7608 \begin_layout Plain Layout
7610         if (cindex>=0) {
7611 \end_layout
7613 \begin_layout Plain Layout
7615           mode = context[cindex, "mode"];
7616 \end_layout
7618 \begin_layout Plain Layout
7620           language = context[cindex, "language"];
7621 \end_layout
7623 \begin_layout Plain Layout
7625           =<
7626 \backslash
7627 chunkref{parse_chunk_args-reset-modes}>
7628 \end_layout
7630 \begin_layout Plain Layout
7632         }
7633 \end_layout
7635 \begin_layout Plain Layout
7637         item = item a[1];
7638 \end_layout
7640 \begin_layout Plain Layout
7642         text = substr(text, 1 + length(part) + length(a[1]));
7643 \end_layout
7645 \begin_layout Plain Layout
7647       }
7648 \end_layout
7650 \end_inset
7653 \end_layout
7655 \begin_layout Standard
7656 If a delimiter was matched, then we must store the current item in the parsed
7657  values array, and reset the item.
7658 \end_layout
7660 \begin_layout Standard
7661 \begin_inset listings
7662 inline false
7663 status open
7665 \begin_layout Plain Layout
7667       else if (match(a[1], "^" delimiters "$")) {
7668 \end_layout
7670 \begin_layout Plain Layout
7672         if (cindex==0) {
7673 \end_layout
7675 \begin_layout Plain Layout
7677           context[cindex, "values", ++context[cindex, "values"]] = item;
7678 \end_layout
7680 \begin_layout Plain Layout
7682           item = "";
7683 \end_layout
7685 \begin_layout Plain Layout
7687         } else {
7688 \end_layout
7690 \begin_layout Plain Layout
7692           item = item a[1];
7693 \end_layout
7695 \begin_layout Plain Layout
7697         }
7698 \end_layout
7700 \begin_layout Plain Layout
7702         text = substr(text, 1 + length(part) + length(a[1]));
7703 \end_layout
7705 \begin_layout Plain Layout
7707       }
7708 \end_layout
7710 \end_inset
7713 \end_layout
7715 \begin_layout Standard
7716 otherwise, if a new submode is detected (all submodes have terminators),
7717  we must create a nested parse context until we find the terminator for
7718  this mode.
7719 \end_layout
7721 \begin_layout Standard
7722 \begin_inset listings
7723 inline false
7724 status open
7726 \begin_layout Plain Layout
7728  else if ((language, a[1], "terminators") in modes) {
7729 \end_layout
7731 \begin_layout Plain Layout
7733         #check if new_mode is defined
7734 \end_layout
7736 \begin_layout Plain Layout
7738         item = item a[1];
7739 \end_layout
7741 \begin_layout Plain Layout
7743 #printf("%2d ENTER MODE [%s] in [%s]
7744 \backslash
7745 n", cindex, a[1], text) > "/dev/stderr"
7746 \end_layout
7748 \begin_layout Plain Layout
7750         text = substr(text, 1 + length(part) + length(a[1]));
7751 \end_layout
7753 \begin_layout Plain Layout
7755         context[""] = ++cindex;
7756 \end_layout
7758 \begin_layout Plain Layout
7760         context[cindex, "mode"] = a[1];
7761 \end_layout
7763 \begin_layout Plain Layout
7765         context[cindex, "language"] = language;
7766 \end_layout
7768 \begin_layout Plain Layout
7770         mode = a[1];
7771 \end_layout
7773 \begin_layout Plain Layout
7775         =<
7776 \backslash
7777 chunkref{parse_chunk_args-reset-modes}>
7778 \end_layout
7780 \begin_layout Plain Layout
7782       } else {
7783 \end_layout
7785 \begin_layout Plain Layout
7787         error(sprintf("Submode '%s' set unknown mode in text: %s
7788 \backslash
7789 nLanguage %s Mode %s
7790 \backslash
7791 n", a[1], text, language, mode));
7792 \end_layout
7794 \begin_layout Plain Layout
7796         text = substr(text, 1 + length(part) + length(a[1]));
7797 \end_layout
7799 \begin_layout Plain Layout
7801       }
7802 \end_layout
7804 \begin_layout Plain Layout
7806     }
7807 \end_layout
7809 \end_inset
7812 \end_layout
7814 \begin_layout Standard
7815 In the final case, we parsed to the end of the string.
7816  If the string was entire, then we should have no nested mode context, but
7817  if the string was just a fragment we may have a mode context which must
7818  be preserved for the next fragment.
7819  Todo: Consideration ought to be given if sub-mode strings are split over
7820  two fragments.
7821 \begin_inset Note Note
7822 status collapsed
7824 \begin_layout Plain Layout
7825 Consideration ought to be given if sub-mode strings are split over two fragments.
7826 \end_layout
7828 \end_inset
7831 \end_layout
7833 \begin_layout Standard
7834 \begin_inset listings
7835 inline false
7836 status open
7838 \begin_layout Plain Layout
7840 else {
7841 \end_layout
7843 \begin_layout Plain Layout
7845       context[cindex, "values", ++context[cindex, "values"]] = item text;
7846 \end_layout
7848 \begin_layout Plain Layout
7850       text = "";
7851 \end_layout
7853 \begin_layout Plain Layout
7855       item = "";
7856 \end_layout
7858 \begin_layout Plain Layout
7860     }
7861 \end_layout
7863 \begin_layout Plain Layout
7865   }
7866 \end_layout
7868 \begin_layout Plain Layout
7870 \end_layout
7872 \begin_layout Plain Layout
7874   context["item"] = item;
7875 \end_layout
7877 \begin_layout Plain Layout
7879 \end_layout
7881 \begin_layout Plain Layout
7883   if (length(item)) context[cindex, "values", ++context[cindex, "values"]]
7884  = item;
7885 \end_layout
7887 \begin_layout Plain Layout
7889   return text;
7890 \end_layout
7892 \begin_layout Plain Layout
7895 \end_layout
7897 \end_inset
7900 \end_layout
7902 \begin_layout Subsubsection
7903 One happy chunk
7904 \end_layout
7906 \begin_layout Standard
7907 All the mode tracker chunks are referred to here:
7908 \end_layout
7910 \begin_layout Chunk
7911 mode-tracker
7912 \end_layout
7914 \begin_layout Standard
7915 \begin_inset listings
7916 inline false
7917 status open
7919 \begin_layout Plain Layout
7922 \backslash
7923 chunkref{new_mode_tracker()}>
7924 \end_layout
7926 \begin_layout Plain Layout
7929 \backslash
7930 chunkref{mode_tracker()}>
7931 \end_layout
7933 \end_inset
7936 \end_layout
7938 \begin_layout Subsubsection
7939 Tests
7940 \end_layout
7942 \begin_layout Standard
7943 We can test this function like this:
7944 \end_layout
7946 \begin_layout Chunk
7947 pca-test.awk
7948 \end_layout
7950 \begin_layout Standard
7951 \begin_inset listings
7952 inline false
7953 status open
7955 \begin_layout Plain Layout
7958 \backslash
7959 chunkref{error()}>
7960 \end_layout
7962 \begin_layout Plain Layout
7965 \backslash
7966 chunkref{mode-tracker}>
7967 \end_layout
7969 \begin_layout Plain Layout
7972 \backslash
7973 chunkref{parse_chunk_args()}>
7974 \end_layout
7976 \begin_layout Plain Layout
7978 BEGIN {
7979 \end_layout
7981 \begin_layout Plain Layout
7983   SUBSEP=".";
7984 \end_layout
7986 \begin_layout Plain Layout
7988   =<
7989 \backslash
7990 chunkref{mode-definitions}>
7991 \end_layout
7993 \begin_layout Plain Layout
7995 \end_layout
7997 \begin_layout Plain Layout
7999   =<
8000 \backslash
8001 chunkref{test:mode-definitions}>
8002 \end_layout
8004 \begin_layout Plain Layout
8007 \end_layout
8009 \end_inset
8012 \end_layout
8014 \begin_layout Chunk
8015 pca-test.awk:summary
8016 \end_layout
8018 \begin_layout Standard
8019 \begin_inset listings
8020 inline false
8021 status open
8023 \begin_layout Plain Layout
8025 if (e) {
8026 \end_layout
8028 \begin_layout Plain Layout
8030   printf "Failed " e
8031 \end_layout
8033 \begin_layout Plain Layout
8035   for (b in a) {
8036 \end_layout
8038 \begin_layout Plain Layout
8040     print "a[" b "] => " a[b];
8041 \end_layout
8043 \begin_layout Plain Layout
8045   }
8046 \end_layout
8048 \begin_layout Plain Layout
8050 } else {
8051 \end_layout
8053 \begin_layout Plain Layout
8055   print "Passed"
8056 \end_layout
8058 \begin_layout Plain Layout
8061 \end_layout
8063 \begin_layout Plain Layout
8065 split("", a);
8066 \end_layout
8068 \begin_layout Plain Layout
8070 e=0;
8071 \end_layout
8073 \end_inset
8076 \end_layout
8078 \begin_layout Standard
8079 which should give this output:
8080 \end_layout
8082 \begin_layout Chunk
8083 pca-test.awk-results
8084 \end_layout
8086 \begin_layout Standard
8087 \begin_inset listings
8088 inline false
8089 status open
8091 \begin_layout Plain Layout
8093 a[foo.quux.quirk] => 
8094 \end_layout
8096 \begin_layout Plain Layout
8098 a[foo.quux.a] => fleeg
8099 \end_layout
8101 \begin_layout Plain Layout
8103 a[foo.bar] => baz
8104 \end_layout
8106 \begin_layout Plain Layout
8108 a[etc] => 
8109 \end_layout
8111 \begin_layout Plain Layout
8113 a[name] => freddie
8114 \end_layout
8116 \end_inset
8119 \end_layout
8121 \begin_layout Section
8122 Escaping and Quoting
8123 \end_layout
8125 \begin_layout Standard
8126 Each nested mode can optionally define a set of transforms to be applied
8127  to any text that is included from another language.
8128 \end_layout
8130 \begin_layout Standard
8131 This code can perform transforms
8132 \end_layout
8134 \begin_layout Chunk
8135 mode_tracker
8136 \end_layout
8138 \begin_layout Standard
8139 \begin_inset listings
8140 inline false
8141 status open
8143 \begin_layout Plain Layout
8145 function transform_escape(s, r, text,
8146 \end_layout
8148 \begin_layout Plain Layout
8150     # optional
8151 \end_layout
8153 \begin_layout Plain Layout
8155     max, 
8156 \end_layout
8158 \begin_layout Plain Layout
8160         # local vars
8161 \end_layout
8163 \begin_layout Plain Layout
8165         c)
8166 \end_layout
8168 \begin_layout Plain Layout
8171 \end_layout
8173 \begin_layout Plain Layout
8175   for(c=1; c <= max && (c in s); c++) {
8176 \end_layout
8178 \begin_layout Plain Layout
8180     gsub(s[c], r[c], text);
8181 \end_layout
8183 \begin_layout Plain Layout
8185   }
8186 \end_layout
8188 \begin_layout Plain Layout
8190   return text;
8191 \end_layout
8193 \begin_layout Plain Layout
8196 \end_layout
8198 \end_inset
8201 \end_layout
8203 \begin_layout Standard
8204 This function must append from index 
8205 \begin_inset Flex CharStyle:Code
8206 status collapsed
8208 \begin_layout Plain Layout
8210 \end_layout
8212 \end_inset
8214  onwards, and escape transforms from the supplied context, and return c
8215  + number of new transforms.
8216 \end_layout
8218 \begin_layout Standard
8219 \begin_inset listings
8220 inline false
8221 status open
8223 \begin_layout Plain Layout
8225 function mode_escaper(context, s, r, src,
8226 \end_layout
8228 \begin_layout Plain Layout
8230   c, cp, cpl)
8231 \end_layout
8233 \begin_layout Plain Layout
8236 \end_layout
8238 \begin_layout Plain Layout
8240         for(c = context[""]; c >= 0; c--) {
8241 \end_layout
8243 \begin_layout Plain Layout
8245                 if ( (context[c, "language"], context[c, "mode"]) in escapes) {
8246 \end_layout
8248 \begin_layout Plain Layout
8250                         cpl = escapes[context[c, "language"], context[c, "mode"]];
8251 \end_layout
8253 \begin_layout Plain Layout
8255                         for (cp = 1; cp <= cpl; cp ++) {
8256 \end_layout
8258 \begin_layout Plain Layout
8260                                 ++src;
8261 \end_layout
8263 \begin_layout Plain Layout
8265                                 s[src] = escapes[context[c, "language"], context[c, "mode"], c, "s"];
8266 \end_layout
8268 \begin_layout Plain Layout
8270                                 r[src] = escapes[context[c, "language"], context[c, "mode"], c, "r"];
8271 \end_layout
8273 \begin_layout Plain Layout
8275                         }
8276 \end_layout
8278 \begin_layout Plain Layout
8280                 }
8281 \end_layout
8283 \begin_layout Plain Layout
8285         }
8286 \end_layout
8288 \begin_layout Plain Layout
8290         return src;
8291 \end_layout
8293 \begin_layout Plain Layout
8296 \end_layout
8298 \end_inset
8301 \end_layout
8303 \begin_layout Chunk
8304 test:escapes
8305 \end_layout
8307 \begin_layout Standard
8308 \begin_inset listings
8309 inline false
8310 status open
8312 \begin_layout Plain Layout
8314 echo escapes test
8315 \end_layout
8317 \begin_layout Plain Layout
8319 passtest ./newfangle -Rtest:comment-quote $TEX_SRC &>/dev/null || ( echo
8320  "Comment-quote failed" && exit 1 )
8321 \end_layout
8323 \end_inset
8326 \end_layout
8328 \begin_layout Chapter
8329 Recognizing Chunks
8330 \end_layout
8332 \begin_layout Standard
8333 Newfangle recognizes noweb chunks, but as we also want better LaTeX integration
8334  we will recognize any of these:
8335 \end_layout
8337 \begin_layout Itemize
8338 notangle chunks matching the pattern 
8339 \begin_inset Flex CharStyle:Code
8340 status collapsed
8342 \begin_layout Plain Layout
8344 \begin_inset space \hspace*{}
8345 \length 0in
8346 \end_inset
8348 <.*?>
8349 \begin_inset space \hspace*{}
8350 \length 0in
8351 \end_inset
8354 \end_layout
8356 \end_inset
8359 \end_layout
8361 \begin_layout Itemize
8362 a chunks beginning with 
8363 \begin_inset Flex CharStyle:Code
8364 status collapsed
8366 \begin_layout Plain Layout
8368 \backslash
8369 begin{lstlistings}
8370 \end_layout
8372 \end_inset
8374 , possibly with 
8375 \backslash
8376 Chunk{\SpecialChar \ldots{}
8377 } on the previous line
8378 \end_layout
8380 \begin_layout Itemize
8381 an older form I have used, beginning with 
8382 \begin_inset Flex CharStyle:Code
8383 status collapsed
8385 \begin_layout Plain Layout
8387 \backslash
8388 begin{Chunk}[options]
8389 \end_layout
8391 \end_inset
8393  --- also more suitable for plain LaTeX users
8394 \begin_inset Foot
8395 status collapsed
8397 \begin_layout Plain Layout
8398 Is there such a thing as plain LaTeX?
8399 \end_layout
8401 \end_inset
8404 \end_layout
8406 \begin_layout Section
8407 Chunk start
8408 \end_layout
8410 \begin_layout Standard
8411 The variable 
8412 \begin_inset Flex CharStyle:Code
8413 status collapsed
8415 \begin_layout Plain Layout
8416 chunking
8417 \end_layout
8419 \end_inset
8421  is used to signify that we are processing a code chunk and not document.
8422  In such a state, input lines will be assigned to the current chunk; otherwise
8423  they are ignored.
8424 \end_layout
8426 \begin_layout Subsection
8427 lstlistings
8428 \end_layout
8430 \begin_layout Standard
8431 Our current scheme is to recognize the new lstlisting chunks, but these
8432  may be preceded by a 
8433 \begin_inset Flex CharStyle:Code
8434 status collapsed
8436 \begin_layout Plain Layout
8438 \backslash
8439 Chunk
8440 \end_layout
8442 \end_inset
8444  command which in LyX is a more convenient way to pass the chunk name to
8445  the 
8446 \begin_inset Flex CharStyle:Code
8447 status collapsed
8449 \begin_layout Plain Layout
8451 \backslash
8452 begin{lstlistings}
8453 \end_layout
8455 \end_inset
8457  command, and a more visible way to specify other 
8458 \begin_inset Flex CharStyle:Code
8459 status collapsed
8461 \begin_layout Plain Layout
8462 lstset
8463 \end_layout
8465 \end_inset
8467  settings.
8468 \end_layout
8470 \begin_layout Standard
8471 The arguments to the 
8472 \begin_inset Flex CharStyle:Code
8473 status collapsed
8475 \begin_layout Plain Layout
8477 \backslash
8478 Chunk
8479 \end_layout
8481 \end_inset
8483  command are a name, and then a comma-seperated list of key-value pairs
8484  after the manner of 
8485 \begin_inset Flex CharStyle:Code
8486 status collapsed
8488 \begin_layout Plain Layout
8490 \backslash
8491 lstset
8492 \end_layout
8494 \end_inset
8497  (In fact within the LaTeX 
8498 \begin_inset Flex CharStyle:Code
8499 status collapsed
8501 \begin_layout Plain Layout
8503 \backslash
8504 Chunk
8505 \end_layout
8507 \end_inset
8509  macro (section 
8510 \begin_inset CommandInset ref
8511 LatexCommand ref
8512 reference "sub:The-chunk-command"
8514 \end_inset
8516 ) the text 
8517 \begin_inset Flex CharStyle:Code
8518 status collapsed
8520 \begin_layout Plain Layout
8521 name=
8522 \end_layout
8524 \end_inset
8526  is prefixed to the argument which is then literally passed to 
8527 \begin_inset Flex CharStyle:Code
8528 status collapsed
8530 \begin_layout Plain Layout
8532 \backslash
8533 lstset
8534 \end_layout
8536 \end_inset
8539 \end_layout
8541 \begin_layout Chunk
8542 recognize-chunk
8543 \end_layout
8545 \begin_layout Standard
8546 \begin_inset listings
8547 inline false
8548 status open
8550 \begin_layout Plain Layout
8553 \backslash
8555 \backslash
8556 Chunk{/ {
8557 \end_layout
8559 \begin_layout Plain Layout
8561   if (match($0, "^
8562 \backslash
8564 \backslash
8566 \backslash
8568 \backslash
8569 Chunk{ *([^ ,}]*),?(.*)}", line)) {
8570 \end_layout
8572 \begin_layout Plain Layout
8574     next_chunk_name = line[1];
8575 \end_layout
8577 \begin_layout Plain Layout
8579     get_chunk_args(line[2], next_chunk_args);
8580 \end_layout
8582 \begin_layout Plain Layout
8584   }
8585 \end_layout
8587 \begin_layout Plain Layout
8589   next;
8590 \end_layout
8592 \begin_layout Plain Layout
8595 \end_layout
8597 \end_inset
8600 \end_layout
8602 \begin_layout Standard
8603 We also make a basic attempt to parse the name out of the 
8604 \begin_inset Flex CharStyle:Code
8605 status collapsed
8607 \begin_layout Plain Layout
8609 \backslash
8610 lstlistings[name=
8611 \begin_inset space \hspace{}
8612 \length 0in
8613 \end_inset
8615 chunk-name]
8616 \end_layout
8618 \end_inset
8620  text, otherwise we fall back to the name found in the previous chunk command.
8621  This attempt is very basic and doesn't support commas or spaces or square
8622  brackets as part of the chunkname.
8623  We also recognize 
8624 \begin_inset Flex CharStyle:Code
8625 status collapsed
8627 \begin_layout Plain Layout
8629 \backslash
8630 begin{Chunk}
8631 \end_layout
8633 \end_inset
8635  which is convenient for some users
8636 \begin_inset Foot
8637 status open
8639 \begin_layout Plain Layout
8640 but not yet supported in the LaTeX macros
8641 \end_layout
8643 \end_inset
8646 \begin_inset Note Note
8647 status collapsed
8649 \begin_layout Plain Layout
8650 Add noweave support
8651 \end_layout
8653 \end_inset
8656 \end_layout
8658 \begin_layout Standard
8659 \begin_inset listings
8660 inline false
8661 status open
8663 \begin_layout Plain Layout
8666 \backslash
8668 \backslash
8669 begin{lstlisting}|^
8670 \backslash
8672 \backslash
8673 begin{Chunk}/ {
8674 \end_layout
8676 \begin_layout Plain Layout
8678   if (match($0, "}.*[[,] *name= *{? *([^], }]*)", line)) {
8679 \end_layout
8681 \begin_layout Plain Layout
8683     new_chunk(line[1]);
8684 \end_layout
8686 \begin_layout Plain Layout
8688   } else {
8689 \end_layout
8691 \begin_layout Plain Layout
8693     new_chunk(next_chunk_name, next_chunk_args);
8694 \end_layout
8696 \begin_layout Plain Layout
8698   }
8699 \end_layout
8701 \begin_layout Plain Layout
8703   chunking=1;
8704 \end_layout
8706 \begin_layout Plain Layout
8708   next;
8709 \end_layout
8711 \begin_layout Plain Layout
8714 \end_layout
8716 \end_inset
8719 \end_layout
8721 \begin_layout Subsection
8722 Noweb
8723 \end_layout
8725 \begin_layout Standard
8726 We recognize notangle style chunks too:
8727 \end_layout
8729 \begin_layout Chunk
8730 recognize-chunk
8731 \end_layout
8733 \begin_layout Standard
8734 \begin_inset listings
8735 inline false
8736 status open
8738 \begin_layout Plain Layout
8740 /^[<]<.*[>]>=/ {
8741 \end_layout
8743 \begin_layout Plain Layout
8745   if (match($0, "^[<]<(.*)[>]>= *$", line)) {
8746 \end_layout
8748 \begin_layout Plain Layout
8750     chunking=1;
8751 \end_layout
8753 \begin_layout Plain Layout
8755     notangle_mode=1;
8756 \end_layout
8758 \begin_layout Plain Layout
8760     new_chunk(line[1]);
8761 \end_layout
8763 \begin_layout Plain Layout
8765     next;
8766 \end_layout
8768 \begin_layout Plain Layout
8770   }
8771 \end_layout
8773 \begin_layout Plain Layout
8776 \end_layout
8778 \end_inset
8781 \end_layout
8783 \begin_layout Section
8784 Chunk end
8785 \end_layout
8787 \begin_layout Standard
8788 Likewise, we need to recognize when a chunk ends.
8789 \end_layout
8791 \begin_layout Subsection
8792 lstlistings
8793 \end_layout
8795 \begin_layout Standard
8796 The 
8797 \begin_inset Flex CharStyle:Code
8798 status collapsed
8800 \begin_layout Plain Layout
8802 \end_layout
8804 \end_inset
8806  in 
8807 \begin_inset Flex CharStyle:Code
8808 status collapsed
8810 \begin_layout Plain Layout
8811 [e]end{lislisting}
8812 \end_layout
8814 \end_inset
8816  is surrounded by square brackets so that when this document is processed,
8817  this chunk doesn't terminate early when the lstlistings package recognizes
8818  it's own end-string! 
8819 \begin_inset Note Greyedout
8820 status collapsed
8822 \begin_layout Plain Layout
8823 This doesn't make sense as the regex is anchored with ^, which this line
8824  does not begin with!
8825 \end_layout
8827 \end_inset
8830 \begin_inset Note Note
8831 status open
8833 \begin_layout Plain Layout
8834 No, it doesn't.
8835 \end_layout
8837 \end_inset
8840 \end_layout
8842 \begin_layout Chunk
8843 recognize-chunk
8844 \end_layout
8846 \begin_layout Standard
8847 \begin_inset listings
8848 inline false
8849 status open
8851 \begin_layout Plain Layout
8854 \backslash
8856 \backslash
8857 [e]nd{lstlisting}|^
8858 \backslash
8860 \backslash
8861 [e]nd{Chunk}/ {
8862 \end_layout
8864 \begin_layout Plain Layout
8866   chunking=0;
8867 \end_layout
8869 \begin_layout Plain Layout
8871   active_chunk="";
8872 \end_layout
8874 \begin_layout Plain Layout
8876   next;
8877 \end_layout
8879 \begin_layout Plain Layout
8882 \end_layout
8884 \end_inset
8887 \end_layout
8889 \begin_layout Subsection
8890 noweb
8891 \end_layout
8893 \begin_layout Chunk
8894 recognize-chunk
8895 \end_layout
8897 \begin_layout Standard
8898 \begin_inset listings
8899 inline false
8900 status open
8902 \begin_layout Plain Layout
8904 /^@ *$/ {
8905 \end_layout
8907 \begin_layout Plain Layout
8909   chunking=0;
8910 \end_layout
8912 \begin_layout Plain Layout
8914   active_chunk="";
8915 \end_layout
8917 \begin_layout Plain Layout
8920 \end_layout
8922 \end_inset
8925 \end_layout
8927 \begin_layout Standard
8928 All other recognizers are only of effect if we are chunking; there's no
8929  point in looking at lines if they aren't part of a chunk, so we just ignore
8930  them as efficiently as we can.
8931 \end_layout
8933 \begin_layout Chunk
8934 recognize-chunk
8935 \end_layout
8937 \begin_layout Standard
8938 \begin_inset listings
8939 inline false
8940 status open
8942 \begin_layout Plain Layout
8944 ! chunking { next; }
8945 \end_layout
8947 \end_inset
8950 \end_layout
8952 \begin_layout Section
8953 Chunk contents
8954 \end_layout
8956 \begin_layout Standard
8957 Chunk contents are any lines read while 
8958 \begin_inset Flex CharStyle:Code
8959 status collapsed
8961 \begin_layout Plain Layout
8962 chunking
8963 \end_layout
8965 \end_inset
8967  is true.
8968  Some chunk contents are special in that they refer to other chunks, and
8969  will be replaced by the contents of these chunks when the file is generated.
8970 \end_layout
8972 \begin_layout Standard
8973 \begin_inset CommandInset label
8974 LatexCommand label
8975 name "sub:ORS-chunk-text"
8977 \end_inset
8979 We add the output record separator 
8980 \begin_inset Flex CharStyle:Code
8981 status collapsed
8983 \begin_layout Plain Layout
8985 \end_layout
8987 \end_inset
8989  to the line now, because we will set 
8990 \begin_inset Flex CharStyle:Code
8991 status collapsed
8993 \begin_layout Plain Layout
8995 \end_layout
8997 \end_inset
8999  to the empty string when we generate the output
9000 \begin_inset Foot
9001 status collapsed
9003 \begin_layout Plain Layout
9004 So that we can print partial lines using 
9005 \begin_inset Flex CharStyle:Code
9006 status collapsed
9008 \begin_layout Plain Layout
9009 print
9010 \end_layout
9012 \end_inset
9014  instead of 
9015 \begin_inset Flex CharStyle:Code
9016 status collapsed
9018 \begin_layout Plain Layout
9019 printf
9020 \end_layout
9022 \end_inset
9025 \end_layout
9027 \end_inset
9030 \end_layout
9032 \begin_layout Chunk
9033 recognize-chunk
9034 \end_layout
9036 \begin_layout Standard
9037 \begin_inset listings
9038 inline false
9039 status open
9041 \begin_layout Plain Layout
9043 length(active_chunk) {
9044 \end_layout
9046 \begin_layout Plain Layout
9048   =<
9049 \backslash
9050 chunkref{process-chunk-tabs}>
9051 \end_layout
9053 \begin_layout Plain Layout
9055   =<
9056 \backslash
9057 chunkref{process-chunk}>
9058 \end_layout
9060 \begin_layout Plain Layout
9063 \end_layout
9065 \end_inset
9068 \end_layout
9070 \begin_layout Standard
9071 If a chunk just consisted of plain text, we could handle the chunk like
9072  this:
9073 \end_layout
9075 \begin_layout Chunk
9076 process-chunk-simple
9077 \end_layout
9079 \begin_layout Standard
9080 \begin_inset listings
9081 inline false
9082 status open
9084 \begin_layout Plain Layout
9086 chunk_line(active_chunk, $0 ORS);
9087 \end_layout
9089 \end_inset
9092 \end_layout
9094 \begin_layout Standard
9095 but in fact a chunk can include references to other chunks.
9096  Chunk includes are traditionally written as 
9097 \begin_inset Flex CharStyle:Code
9098 status collapsed
9100 \begin_layout Plain Layout
9101 <<chunk-name>>
9102 \end_layout
9104 \end_inset
9106 , but we support other variations.
9107 \end_layout
9109 \begin_layout Standard
9110 However, we also process tabs at this point, a tab at input can be replaced
9111  by a number of spaces defined by the 
9112 \begin_inset Flex CharStyle:Code
9113 status collapsed
9115 \begin_layout Plain Layout
9116 tabs
9117 \end_layout
9119 \end_inset
9121  variable, set by the 
9122 \begin_inset Flex CharStyle:Code
9123 status collapsed
9125 \begin_layout Plain Layout
9127 \end_layout
9129 \end_inset
9131  option.
9132  Of course this is poor tab behaviour, we should probably have the option
9133  to use proper counted tab-stops and process this on output.
9134 \end_layout
9136 \begin_layout Chunk
9137 process-chunk-tabs
9138 \end_layout
9140 \begin_layout Standard
9141 \begin_inset listings
9142 inline false
9143 status open
9145 \begin_layout Plain Layout
9147 if (length(tabs)) {
9148 \end_layout
9150 \begin_layout Plain Layout
9152   gsub("
9153 \backslash
9154 t", tabs);
9155 \end_layout
9157 \begin_layout Plain Layout
9160 \end_layout
9162 \end_inset
9165 \end_layout
9167 \begin_layout Subsection
9168 \begin_inset CommandInset label
9169 LatexCommand label
9170 name "sub:lstlistings-includes"
9172 \end_inset
9174 lstlistings
9175 \end_layout
9177 \begin_layout Standard
9178 If 
9179 \begin_inset Flex CharStyle:Code
9180 status collapsed
9182 \begin_layout Plain Layout
9184 \backslash
9185 lstset{escapeinside={=<}{>}}
9186 \end_layout
9188 \end_inset
9190  is set, then we can use 
9191 \begin_inset Flex CharStyle:Code
9192 status collapsed
9194 \begin_layout Plain Layout
9196 \backslash
9197 chunkref{
9198 \begin_inset space \hspace{}
9199 \length 0in
9200 \end_inset
9202 chunk-name}>
9203 \end_layout
9205 \end_inset
9207  in listings.
9208  The sequence 
9209 \begin_inset Flex CharStyle:Code
9210 status collapsed
9212 \begin_layout Plain Layout
9214 \end_layout
9216 \end_inset
9218  was chosen because:
9219 \end_layout
9221 \begin_layout Enumerate
9222 it is a better mnemonic than 
9223 \begin_inset Flex CharStyle:Code
9224 status collapsed
9226 \begin_layout Plain Layout
9227 <<chunk-name>>
9228 \end_layout
9230 \end_inset
9232  in that the = sign signifies equivalent or substitutability, 
9233 \end_layout
9235 \begin_layout Enumerate
9236 and because =< is not valid in C or in any language I can think of 
9237 \end_layout
9239 \begin_layout Enumerate
9240 and also because lstlistings doesn't like 
9241 \begin_inset Flex CharStyle:Code
9242 status collapsed
9244 \begin_layout Plain Layout
9246 \end_layout
9248 \end_inset
9250  as an end delimiter for the 
9251 \emph on
9252 texcl
9253 \emph default
9254  escape, so we must make do with a single 
9255 \begin_inset Flex CharStyle:Code
9256 status collapsed
9258 \begin_layout Plain Layout
9260 \end_layout
9262 \end_inset
9264 , which is better matched by 
9265 \begin_inset Flex CharStyle:Code
9266 status collapsed
9268 \begin_layout Plain Layout
9270 \end_layout
9272 \end_inset
9274  than 
9275 \begin_inset Flex CharStyle:Code
9276 status collapsed
9278 \begin_layout Plain Layout
9280 \end_layout
9282 \end_inset
9285 \end_layout
9287 \begin_layout Standard
9288 Unfortunately 
9289 \begin_inset Note Note
9290 status open
9292 \begin_layout Plain Layout
9293 fix this then
9294 \end_layout
9296 \end_inset
9298  the 
9299 \begin_inset Flex CharStyle:Code
9300 status collapsed
9302 \begin_layout Plain Layout
9303 =<\SpecialChar \ldots{}
9305 \end_layout
9307 \end_inset
9309  that we use re-enters a LaTeX parsing mode in which some characters are
9310  special, e.g.
9312 \begin_inset Flex CharStyle:Code
9313 status collapsed
9315 \begin_layout Plain Layout
9317 \backslash
9319 \end_layout
9321 \end_inset
9323 , and so these cause trouble if used in arguments to 
9324 \begin_inset Flex CharStyle:Code
9325 status collapsed
9327 \begin_layout Plain Layout
9329 \backslash
9330 chunkref
9331 \end_layout
9333 \end_inset
9336  At some point I must fix the LaTeX command 
9337 \begin_inset Flex CharStyle:Code
9338 status collapsed
9340 \begin_layout Plain Layout
9342 \backslash
9343 chunkref
9344 \end_layout
9346 \end_inset
9348  so that it can accept these literally, but until then, when writing chunkref
9349  argumemts that need these characters, I must use the forms 
9350 \begin_inset Flex CharStyle:Code
9351 status collapsed
9353 \begin_layout Plain Layout
9355 \backslash
9356 textbackslash{}
9357 \end_layout
9359 \end_inset
9361  and 
9362 \begin_inset Flex CharStyle:Code
9363 status collapsed
9365 \begin_layout Plain Layout
9367 \backslash
9369 \end_layout
9371 \end_inset
9373 ; so I also define a hacky chunk 
9374 \begin_inset Flex CharStyle:Code
9375 status collapsed
9377 \begin_layout Plain Layout
9378 delatex
9379 \end_layout
9381 \end_inset
9383  whose purpose it is to remove these from any arguments parsed by newfangle,
9384  and used further on.
9385 \end_layout
9387 \begin_layout Chunk
9388 delatex,params=text
9389 \end_layout
9391 \begin_layout Standard
9392 \begin_inset listings
9393 inline false
9394 status open
9396 \begin_layout Plain Layout
9398 # FILTHY HACK
9399 \end_layout
9401 \begin_layout Plain Layout
9403 gsub("
9404 \backslash
9406 \backslash
9408 \backslash
9410 \backslash
9411 #", "#", ${text});
9412 \end_layout
9414 \begin_layout Plain Layout
9416 gsub("
9417 \backslash
9419 \backslash
9421 \backslash
9423 \backslash
9424 textbackslash{}", "
9425 \backslash
9427 \backslash
9428 ", ${text});
9429 \end_layout
9431 \end_inset
9434 \end_layout
9436 \begin_layout Standard
9437 As each chunk line may contain more than one chunk include, we will split
9438  out chunk includes in an iterative fashion
9439 \begin_inset Foot
9440 status collapsed
9442 \begin_layout Plain Layout
9443 Contrary to our use of 
9444 \begin_inset Flex CharStyle:Code
9445 status collapsed
9447 \begin_layout Plain Layout
9448 split
9449 \end_layout
9451 \end_inset
9453  when substituting parameters in chapter 
9454 \begin_inset CommandInset ref
9455 LatexCommand ref
9456 reference "Here-we-split"
9458 \end_inset
9461 \end_layout
9463 \end_inset
9466 \end_layout
9468 \begin_layout Standard
9469 First, as long as the chunk contains a 
9470 \begin_inset Flex CharStyle:Code
9471 status collapsed
9473 \begin_layout Plain Layout
9475 \backslash
9476 chunkref
9477 \end_layout
9479 \end_inset
9481  command we take as much as we can up to the first 
9482 \begin_inset Flex CharStyle:Code
9483 status collapsed
9485 \begin_layout Plain Layout
9487 \backslash
9488 chunkref
9489 \end_layout
9491 \end_inset
9493  command.
9494 \end_layout
9496 \begin_layout Chunk
9497 process-chunk
9498 \end_layout
9500 \begin_layout Standard
9501 \begin_inset listings
9502 inline false
9503 status open
9505 \begin_layout Plain Layout
9507 chunk = $0;
9508 \end_layout
9510 \begin_layout Plain Layout
9512 indent = 0;
9513 \end_layout
9515 \begin_layout Plain Layout
9517 while(match(chunk, 
9518 \end_layout
9520 \begin_layout Plain Layout
9522             "([=]<
9523 \backslash
9525 \backslash
9527 \backslash
9529 \backslash
9530 chunkref{([^}>]*)}(
9531 \backslash
9533 \backslash
9535 \backslash
9537 \backslash
9538 )|)>|<<([a-zA-Z_][-a-zA-Z0-9_]*)>>)", 
9539 \end_layout
9541 \begin_layout Plain Layout
9543             line)
9544 \backslash
9546 \end_layout
9548 \begin_layout Plain Layout
9550 ) {
9551 \end_layout
9553 \begin_layout Plain Layout
9555   chunklet = substr(chunk, 1, RSTART - 1);
9556 \end_layout
9558 \end_inset
9561 \end_layout
9563 \begin_layout Standard
9564 We keep track of the indent count, by counting the number of literal characters
9565  found.
9566  We can then preserve this indent on each output line when multi-line chunks
9567  are expanded.
9568 \end_layout
9570 \begin_layout Standard
9571 We then process this first part literal text, and set the chunk which is
9572  still to be processed to be the text after the 
9573 \begin_inset Flex CharStyle:Code
9574 status collapsed
9576 \begin_layout Plain Layout
9578 \backslash
9579 chunkref
9580 \end_layout
9582 \end_inset
9584  command, which we will process next as we continue around the loop.
9585 \end_layout
9587 \begin_layout Standard
9588 \begin_inset listings
9589 inline false
9590 status open
9592 \begin_layout Plain Layout
9594   indent += length(chunklet);
9595 \end_layout
9597 \begin_layout Plain Layout
9599   chunk_line(active_chunk, chunklet);
9600 \end_layout
9602 \begin_layout Plain Layout
9604   chunk = substr(chunk, RSTART + RLENGTH);
9605 \end_layout
9607 \end_inset
9610 \end_layout
9612 \begin_layout Standard
9613 We then consider the type of chunk command we have found, whether it is
9614  the newfangle style command beginning with 
9615 \begin_inset Flex CharStyle:Code
9616 status collapsed
9618 \begin_layout Plain Layout
9620 \end_layout
9622 \end_inset
9624  or the older notangle style beginning with 
9625 \begin_inset Flex CharStyle:Code
9626 status collapsed
9628 \begin_layout Plain Layout
9630 \end_layout
9632 \end_inset
9636 \end_layout
9638 \begin_layout Standard
9639 Newfangle chunks may have parameters contained within square brackets.
9640  These will be matched in 
9641 \begin_inset Flex CharStyle:Code
9642 status collapsed
9644 \begin_layout Plain Layout
9645 line[3]
9646 \end_layout
9648 \end_inset
9650  and are considered at this stage of processing to be part of the name of
9651  the chunk to be included.
9652 \end_layout
9654 \begin_layout Standard
9655 \begin_inset listings
9656 inline false
9657 status open
9659 \begin_layout Plain Layout
9661   if (substr(line[1], 1, 1) == "=") {
9662 \end_layout
9664 \begin_layout Plain Layout
9666     # chunk name up to }
9667 \end_layout
9669 \begin_layout Plain Layout
9671         =<
9672 \backslash
9673 chunkref{delatex}(line[3])>
9674 \end_layout
9676 \begin_layout Plain Layout
9678     chunk_include(active_chunk, line[2] line[3], indent);
9679 \end_layout
9681 \begin_layout Plain Layout
9683   } else if (substr(line[1], 1, 1) == "<") {
9684 \end_layout
9686 \begin_layout Plain Layout
9688     chunk_include(active_chunk, line[4], indent);
9689 \end_layout
9691 \begin_layout Plain Layout
9693   } else {
9694 \end_layout
9696 \begin_layout Plain Layout
9698     error("Unknown chunk fragment: " line[1]);
9699 \end_layout
9701 \begin_layout Plain Layout
9703   }
9704 \end_layout
9706 \end_inset
9709 \end_layout
9711 \begin_layout Standard
9712 The loop will continue until there are no more chunkref statements in the
9713  text, at which point we process the final part of the chunk.
9714 \end_layout
9716 \begin_layout Standard
9717 \begin_inset listings
9718 inline false
9719 status open
9721 \begin_layout Plain Layout
9724 \end_layout
9726 \begin_layout Plain Layout
9728 chunk_line(active_chunk, chunk);
9729 \end_layout
9731 \end_inset
9734 \end_layout
9736 \begin_layout Standard
9737 \begin_inset CommandInset label
9738 LatexCommand label
9739 name "lone-newline"
9741 \end_inset
9743 We add the newline character as a chunklet on it's own, to make it easier
9744  to detect new lines and thus manage indentation when processing the output.
9745 \end_layout
9747 \begin_layout Standard
9748 \begin_inset listings
9749 inline false
9750 status open
9752 \begin_layout Plain Layout
9754 chunk_line(active_chunk, "
9755 \backslash
9756 n");
9757 \end_layout
9759 \end_inset
9762 \end_layout
9764 \begin_layout Standard
9765 We will also permit a chunk-part number to follow in square brackets, so
9766  that 
9767 \begin_inset Flex CharStyle:Code
9768 status collapsed
9770 \begin_layout Plain Layout
9772 \backslash
9773 chunkref{chunk-name[1]}>
9774 \end_layout
9776 \end_inset
9778  will refer to the first part only.
9779  This can make it easy to include a C function prototype in a header file,
9780  if the first part of the chunk is just the function prototype without the
9781  trailing semi-colon.
9782  The header file would include the prototype with the trailing semi-colon,
9783  like this:
9784 \end_layout
9786 \begin_layout LyX-Code
9788 \backslash
9789 chunkref{chunk-name[1]}>;
9790 \end_layout
9792 \begin_layout Standard
9793 This is handled in section 
9794 \begin_inset CommandInset ref
9795 LatexCommand ref
9796 reference "sub:Chunk-parts"
9798 \end_inset
9801 \end_layout
9803 \begin_layout Standard
9804 We should perhaps introduce a notion of language specific chunk options;
9805  so that perhaps we could specify:
9806 \end_layout
9808 \begin_layout LyX-Code
9810 \backslash
9811 chunkref{chunk-name[function-declaration]}>;
9812 \end_layout
9814 \begin_layout Standard
9815 which applies a transform 
9816 \begin_inset Flex CharStyle:Code
9817 status collapsed
9819 \begin_layout Plain Layout
9820 function-declaration
9821 \end_layout
9823 \end_inset
9825  to the chunk --- which in this case would extract a function prototype
9826  from a function.
9827 \begin_inset Note Note
9828 status open
9830 \begin_layout Plain Layout
9831 So do it
9832 \end_layout
9834 \end_inset
9837 \end_layout
9839 \begin_layout Chapter
9840 Processing Options
9841 \end_layout
9843 \begin_layout Standard
9844 At the start, first we set the default options.
9845 \end_layout
9847 \begin_layout Chunk
9848 default-options
9849 \end_layout
9851 \begin_layout Standard
9852 \begin_inset listings
9853 inline false
9854 status open
9856 \begin_layout Plain Layout
9858 debug=0;
9859 \end_layout
9861 \begin_layout Plain Layout
9863 linenos=0;
9864 \end_layout
9866 \begin_layout Plain Layout
9868 notangle_mode=0;
9869 \end_layout
9871 \begin_layout Plain Layout
9873 root="*";
9874 \end_layout
9876 \begin_layout Plain Layout
9878 tabs = "";
9879 \end_layout
9881 \end_inset
9884 \end_layout
9886 \begin_layout Standard
9887 Then we use getopt the standard way, and null out ARGV afterwards in the
9888  normal AWK fashion.
9889 \end_layout
9891 \begin_layout Chunk
9892 read-options
9893 \end_layout
9895 \begin_layout Standard
9896 \begin_inset listings
9897 inline false
9898 status open
9900 \begin_layout Plain Layout
9902 Optind = 1    # skip ARGV[0]
9903 \end_layout
9905 \begin_layout Plain Layout
9907 while(getopt(ARGC, ARGV, "R:LdT:hr")!=-1) {
9908 \end_layout
9910 \begin_layout Plain Layout
9912   =<
9913 \backslash
9914 chunkref{handle-options}>
9915 \end_layout
9917 \begin_layout Plain Layout
9920 \end_layout
9922 \begin_layout Plain Layout
9924 for (i=1; i<Optind; i++) { ARGV[i]=""; }
9925 \end_layout
9927 \end_inset
9930 \end_layout
9932 \begin_layout Standard
9933 This is how we handle our options:
9934 \end_layout
9936 \begin_layout Chunk
9937 handle-options
9938 \end_layout
9940 \begin_layout Standard
9941 \begin_inset listings
9942 inline false
9943 status open
9945 \begin_layout Plain Layout
9947 if (Optopt == "R") root = Optarg;
9948 \end_layout
9950 \begin_layout Plain Layout
9952 else if (Optopt == "r") root="";
9953 \end_layout
9955 \begin_layout Plain Layout
9957 else if (Optopt == "L") linenos = 1;
9958 \end_layout
9960 \begin_layout Plain Layout
9962 else if (Optopt == "d") debug = 1;
9963 \end_layout
9965 \begin_layout Plain Layout
9967 else if (Optopt == "T") tabs = indent_string(Optarg+0);
9968 \end_layout
9970 \begin_layout Plain Layout
9972 else if (Optopt == "h") help();
9973 \end_layout
9975 \begin_layout Plain Layout
9977 else if (Optopt == "?") help();
9978 \end_layout
9980 \end_inset
9983 \end_layout
9985 \begin_layout Standard
9986 We do all of this at the beginning of the program
9987 \end_layout
9989 \begin_layout Chunk
9990 begin
9991 \end_layout
9993 \begin_layout Standard
9994 \begin_inset listings
9995 inline false
9996 status open
9998 \begin_layout Plain Layout
10000 BEGIN {
10001 \end_layout
10003 \begin_layout Plain Layout
10005   =<
10006 \backslash
10007 chunkref{constants}>
10008 \end_layout
10010 \begin_layout Plain Layout
10012   =<
10013 \backslash
10014 chunkref{mode-definitions}>
10015 \end_layout
10017 \begin_layout Plain Layout
10019   =<
10020 \backslash
10021 chunkref{default-options}>
10022 \end_layout
10024 \begin_layout Plain Layout
10026 \end_layout
10028 \begin_layout Plain Layout
10030   =<
10031 \backslash
10032 chunkref{read-options}>
10033 \end_layout
10035 \begin_layout Plain Layout
10038 \end_layout
10040 \end_inset
10043 \end_layout
10045 \begin_layout Standard
10046 And have a simple help function
10047 \end_layout
10049 \begin_layout Chunk
10050 help()
10051 \end_layout
10053 \begin_layout Standard
10054 \begin_inset listings
10055 inline false
10056 status open
10058 \begin_layout Plain Layout
10060 function help() {
10061 \end_layout
10063 \begin_layout Plain Layout
10065   print "Usage:"
10066 \end_layout
10068 \begin_layout Plain Layout
10070   print "  newfangle [-L] -R<rootname> [source.tex ...]"
10071 \end_layout
10073 \begin_layout Plain Layout
10075   print "  newfangle -r [source.tex ...]"
10076 \end_layout
10078 \begin_layout Plain Layout
10080   print "  If the filename, source.tex is not specified then stdin is used"
10081 \end_layout
10083 \begin_layout Plain Layout
10085   print
10086 \end_layout
10088 \begin_layout Plain Layout
10090   print "-L causes the C statement: #line <lineno> 
10091 \backslash
10092 "filename
10093 \backslash
10094 "" to be issued"
10095 \end_layout
10097 \begin_layout Plain Layout
10099   print "-R causes the named root to be written to stdout"
10100 \end_layout
10102 \begin_layout Plain Layout
10104   print "-r lists all roots in the file (even those used elsewhere)"
10105 \end_layout
10107 \begin_layout Plain Layout
10109   exit 1;
10110 \end_layout
10112 \begin_layout Plain Layout
10115 \end_layout
10117 \end_inset
10120 \end_layout
10122 \begin_layout Chapter
10123 Generating the output
10124 \end_layout
10126 \begin_layout Standard
10127 We generate output by calling output_chunk, or listing the chunk names.
10128 \end_layout
10130 \begin_layout Chunk
10131 generate-output
10132 \end_layout
10134 \begin_layout Standard
10135 \begin_inset listings
10136 inline false
10137 status open
10139 \begin_layout Plain Layout
10141 if (length(root)) output_chunk(root);
10142 \end_layout
10144 \begin_layout Plain Layout
10146 else output_chunk_names();
10147 \end_layout
10149 \end_inset
10152 \end_layout
10154 \begin_layout Standard
10155 We also have some other output debugging:
10156 \end_layout
10158 \begin_layout Chunk
10159 debug-output
10160 \end_layout
10162 \begin_layout Standard
10163 \begin_inset listings
10164 inline false
10165 status open
10167 \begin_layout Plain Layout
10169 if (debug) {
10170 \end_layout
10172 \begin_layout Plain Layout
10174   print "------ chunk names "
10175 \end_layout
10177 \begin_layout Plain Layout
10179   output_chunk_names();
10180 \end_layout
10182 \begin_layout Plain Layout
10184   print "====== chunks"
10185 \end_layout
10187 \begin_layout Plain Layout
10189   output_chunks();
10190 \end_layout
10192 \begin_layout Plain Layout
10194   print "++++++ debug"
10195 \end_layout
10197 \begin_layout Plain Layout
10199   for (a in chunks) {
10200 \end_layout
10202 \begin_layout Plain Layout
10204     print a "=" chunks[a];
10205 \end_layout
10207 \begin_layout Plain Layout
10209   }
10210 \end_layout
10212 \begin_layout Plain Layout
10215 \end_layout
10217 \end_inset
10220 \end_layout
10222 \begin_layout Standard
10223 We do both of these at the end.
10224  We also set 
10225 \begin_inset Flex CharStyle:Code
10226 status collapsed
10228 \begin_layout Plain Layout
10229 ORS=""
10230 \end_layout
10232 \end_inset
10234  because each chunklet is not necessarily a complete line, and we already
10235  added 
10236 \begin_inset Flex CharStyle:Code
10237 status collapsed
10239 \begin_layout Plain Layout
10241 \end_layout
10243 \end_inset
10245  to each input line in section 
10246 \begin_inset CommandInset ref
10247 LatexCommand ref
10248 reference "sub:ORS-chunk-text"
10250 \end_inset
10253 \end_layout
10255 \begin_layout Chunk
10257 \end_layout
10259 \begin_layout Standard
10260 \begin_inset listings
10261 inline false
10262 status open
10264 \begin_layout Plain Layout
10266 END {
10267 \end_layout
10269 \begin_layout Plain Layout
10271   =<
10272 \backslash
10273 chunkref{debug-output}>
10274 \end_layout
10276 \begin_layout Plain Layout
10278   ORS="";
10279 \end_layout
10281 \begin_layout Plain Layout
10283   =<
10284 \backslash
10285 chunkref{generate-output}>
10286 \end_layout
10288 \begin_layout Plain Layout
10291 \end_layout
10293 \end_inset
10296 \end_layout
10298 \begin_layout Standard
10299 We write chunk names like this.
10300  If we seem to be running in notangle compatibility mode, then we enclose
10301  the name like this 
10302 \begin_inset Flex CharStyle:Code
10303 status collapsed
10305 \begin_layout Plain Layout
10306 <<name>>
10307 \end_layout
10309 \end_inset
10311  the same way notangle does:
10312 \end_layout
10314 \begin_layout Chunk
10315 output_chunk_names()
10316 \end_layout
10318 \begin_layout Standard
10319 \begin_inset listings
10320 inline false
10321 status open
10323 \begin_layout Plain Layout
10325 function output_chunk_names(   c, prefix, suffix) 
10326 \end_layout
10328 \begin_layout Plain Layout
10331 \end_layout
10333 \begin_layout Plain Layout
10335   if (notangle_mode) {
10336 \end_layout
10338 \begin_layout Plain Layout
10340     prefix="<<";
10341 \end_layout
10343 \begin_layout Plain Layout
10345     suffix=">>";
10346 \end_layout
10348 \begin_layout Plain Layout
10350   }
10351 \end_layout
10353 \begin_layout Plain Layout
10355   for (c in chunk_names) {
10356 \end_layout
10358 \begin_layout Plain Layout
10360     print prefix c suffix "
10361 \backslash
10363 \end_layout
10365 \begin_layout Plain Layout
10367   }
10368 \end_layout
10370 \begin_layout Plain Layout
10373 \end_layout
10375 \end_inset
10378 \end_layout
10380 \begin_layout Standard
10381 This function would write out all chunks
10382 \end_layout
10384 \begin_layout Chunk
10385 output_chunks()
10386 \end_layout
10388 \begin_layout Standard
10389 \begin_inset listings
10390 inline false
10391 status open
10393 \begin_layout Plain Layout
10395 function output_chunks(  a) 
10396 \end_layout
10398 \begin_layout Plain Layout
10401 \end_layout
10403 \begin_layout Plain Layout
10405   for (a in chunk_names) {
10406 \end_layout
10408 \begin_layout Plain Layout
10410     output_chunk(chunk_names[a]);
10411 \end_layout
10413 \begin_layout Plain Layout
10415   }
10416 \end_layout
10418 \begin_layout Plain Layout
10421 \end_layout
10423 \begin_layout Plain Layout
10425 \end_layout
10427 \begin_layout Plain Layout
10429 function output_chunk(chunk) {
10430 \end_layout
10432 \begin_layout Plain Layout
10434   newline = 1;
10435 \end_layout
10437 \begin_layout Plain Layout
10439   lineno_needed = linenos;
10440 \end_layout
10442 \begin_layout Plain Layout
10444 \end_layout
10446 \begin_layout Plain Layout
10448   write_chunk(chunk);
10449 \end_layout
10451 \begin_layout Plain Layout
10454 \end_layout
10456 \begin_layout Plain Layout
10458 \end_layout
10460 \end_inset
10463 \end_layout
10465 \begin_layout Section
10466 Assembling the chunks
10467 \end_layout
10469 \begin_layout Standard
10470 \begin_inset Flex CharStyle:Code
10471 status collapsed
10473 \begin_layout Plain Layout
10474 chunk_path
10475 \end_layout
10477 \end_inset
10479  holds a string consisting of the names of all the chunks that resulted
10480  in this chunk being output.
10482 \begin_inset Note Note
10483 status collapsed
10485 \begin_layout Plain Layout
10486 Make sure it includes the line numbers too...
10488 \end_layout
10490 \end_inset
10492 It should probably also contain the source line numbers at which each inclusion
10493  also occured.
10494 \end_layout
10496 \begin_layout Chunk
10497 write_chunk()
10498 \end_layout
10500 \begin_layout Standard
10501 We first initialize the mode tracker for this chunk.
10502 \end_layout
10504 \begin_layout Standard
10505 \begin_inset listings
10506 inline false
10507 status open
10509 \begin_layout Plain Layout
10511 function write_chunk(chunk_name) {
10512 \end_layout
10514 \begin_layout Plain Layout
10516   =<
10517 \backslash
10518 chunkref{awk-delete-array}(context)>
10519 \end_layout
10521 \begin_layout Plain Layout
10523   return write_chunk_r(chunk_name, context);
10524 \end_layout
10526 \begin_layout Plain Layout
10529 \end_layout
10531 \end_inset
10534 \end_layout
10536 \begin_layout Chunk
10537 write_chunk(),emph={chunk_path}
10538 \end_layout
10540 \begin_layout Standard
10541 \begin_inset listings
10542 inline false
10543 status open
10545 \begin_layout Plain Layout
10547 function write_chunk_r(chunk_name, context, indent, tail,
10548 \end_layout
10550 \begin_layout Plain Layout
10552   # optional vars
10553 \end_layout
10555 \begin_layout Plain Layout
10557   chunk_path, chunk_args, 
10558 \end_layout
10560 \begin_layout Plain Layout
10562   s, r, src, new_src, 
10563 \end_layout
10565 \begin_layout Plain Layout
10567   # local vars
10568 \end_layout
10570 \begin_layout Plain Layout
10572   chunk_params, part, max_part, part_line, frag, max_frag, text, 
10573 \end_layout
10575 \begin_layout Plain Layout
10577   chunklet, only_part, call_chunk_args)
10578 \end_layout
10580 \begin_layout Plain Layout
10583 \end_layout
10585 \end_inset
10588 \end_layout
10590 \begin_layout Subsection
10591 \begin_inset CommandInset label
10592 LatexCommand label
10593 name "sub:Chunk-parts"
10595 \end_inset
10597 Chunk parts
10598 \end_layout
10600 \begin_layout Standard
10601 As mentioned in section 
10602 \begin_inset CommandInset ref
10603 LatexCommand ref
10604 reference "sub:lstlistings-includes"
10606 \end_inset
10608 , a chunk name may contain a part specifier in square brackets, limiting
10609  the parts that should be emitted.
10610 \end_layout
10612 \begin_layout Standard
10613 \begin_inset listings
10614 inline false
10615 status open
10617 \begin_layout Plain Layout
10619   if (match(chunk_name, "^(.*)
10620 \backslash
10622 \backslash
10623 [([0-9]*)
10624 \backslash
10626 \backslash
10627 ]$", chunk_name_parts)) {
10628 \end_layout
10630 \begin_layout Plain Layout
10632     chunk_name = chunk_name_parts[1];
10633 \end_layout
10635 \begin_layout Plain Layout
10637     only_part = chunk_name_parts[2];
10638 \end_layout
10640 \begin_layout Plain Layout
10642   }
10643 \end_layout
10645 \end_inset
10648 \end_layout
10650 \begin_layout Standard
10651 We then create a mode tracker 
10652 \end_layout
10654 \begin_layout Standard
10655 \begin_inset listings
10656 inline false
10657 status open
10659 \begin_layout Plain Layout
10661   =<
10662 \backslash
10663 chunkref{new-mode-tracker}(context, chunks[chunk_name, "language"], "")>
10664 \end_layout
10666 \end_inset
10669 \end_layout
10671 \begin_layout Standard
10672 We extract into 
10673 \begin_inset Flex CharStyle:Code
10674 status collapsed
10676 \begin_layout Plain Layout
10677 chunk_params
10678 \end_layout
10680 \end_inset
10682  the names of the parameters that this chunk accepts, whose values were
10683  (optionally) passed in 
10684 \begin_inset Flex CharStyle:Code
10685 status collapsed
10687 \begin_layout Plain Layout
10688 chunk_args
10689 \end_layout
10691 \end_inset
10694 \end_layout
10696 \begin_layout Standard
10697 \begin_inset listings
10698 inline false
10699 status open
10701 \begin_layout Plain Layout
10703   split(chunks[chunk_name, "params"], chunk_params, " *; *");
10704 \end_layout
10706 \end_inset
10709 \end_layout
10711 \begin_layout Standard
10712 To assemble a chunk, we write out each part.
10713 \end_layout
10715 \begin_layout Chunk
10716 write_chunk()
10717 \end_layout
10719 \begin_layout Standard
10720 \begin_inset listings
10721 inline false
10722 status open
10724 \begin_layout Plain Layout
10726   if (! (chunk_name in chunk_names)) {
10727 \end_layout
10729 \begin_layout Plain Layout
10731     error(sprintf(_"The root module <<%s>> was not defined.
10732 \backslash
10733 nUsed by: %s",
10734 \backslash
10736 \end_layout
10738 \begin_layout Plain Layout
10740                   chunk_name, chunk_path));
10741 \end_layout
10743 \begin_layout Plain Layout
10745   }
10746 \end_layout
10748 \begin_layout Plain Layout
10750 \end_layout
10752 \begin_layout Plain Layout
10754   max_part = chunks[chunk_name, "part"];
10755 \end_layout
10757 \begin_layout Plain Layout
10759   for(part = 1; part <= max_part; part++) {
10760 \end_layout
10762 \begin_layout Plain Layout
10764     if (! only_part || part == only_part) {
10765 \end_layout
10767 \begin_layout Plain Layout
10769       =<
10770 \backslash
10771 chunkref{write-part}>
10772 \end_layout
10774 \begin_layout Plain Layout
10776     }
10777 \end_layout
10779 \begin_layout Plain Layout
10781   }
10782 \end_layout
10784 \begin_layout Plain Layout
10786   if (! finalize_mode_tracker(context)) {
10787 \end_layout
10789 \begin_layout Plain Layout
10791     error(sprintf(_"Module %s did not close context properly.
10792 \backslash
10793 nUsed by: %s
10794 \backslash
10795 n", chunk_name, chunk_path));
10796 \end_layout
10798 \begin_layout Plain Layout
10800   }
10801 \end_layout
10803 \begin_layout Plain Layout
10806 \end_layout
10808 \end_inset
10811 \end_layout
10813 \begin_layout Standard
10814 A part can either be a chunklet of lines, or an include of another chunk.
10815 \end_layout
10817 \begin_layout Standard
10818 Chunks may also have parameters, specified in LaTeX style with braces after
10819  the chunk name --- looking like this in the document: 
10820 \begin_inset Flex CharStyle:Code
10821 status collapsed
10823 \begin_layout Plain Layout
10824 chunkname{param1, param2}
10825 \end_layout
10827 \end_inset
10830  Arguments are passed in square brackets: 
10831 \begin_inset Flex CharStyle:Code
10832 status collapsed
10834 \begin_layout Plain Layout
10836 \backslash
10837 chunkref{chunkname}[arg1, arg2]
10838 \end_layout
10840 \end_inset
10843 \end_layout
10845 \begin_layout Standard
10846 Before we process each part, we check that the source position hasn't changed
10847  unexpectedly, so that we can know if we need to output a new file-line
10848  directive.
10849 \end_layout
10851 \begin_layout Chunk
10852 write-part
10853 \end_layout
10855 \begin_layout Standard
10856 \begin_inset listings
10857 inline false
10858 status open
10860 \begin_layout Plain Layout
10863 \backslash
10864 chunkref{check-source-jump}>
10865 \end_layout
10867 \begin_layout Plain Layout
10869 \end_layout
10871 \begin_layout Plain Layout
10873 chunklet = chunks[chunk_name, "part", part];
10874 \end_layout
10876 \begin_layout Plain Layout
10878 if (chunks[chunk_name, "part", part, "type"] == part_type_chunk) {
10879 \end_layout
10881 \begin_layout Plain Layout
10883   =<
10884 \backslash
10885 chunkref{write-included-chunk}>
10886 \end_layout
10888 \begin_layout Plain Layout
10890 } else if (chunklet SUBSEP "line" in chunks) {
10891 \end_layout
10893 \begin_layout Plain Layout
10895   =<
10896 \backslash
10897 chunkref{write-chunklets}>
10898 \end_layout
10900 \begin_layout Plain Layout
10902 } else {
10903 \end_layout
10905 \begin_layout Plain Layout
10907   # empty last chunklet
10908 \end_layout
10910 \begin_layout Plain Layout
10913 \end_layout
10915 \end_inset
10918 \end_layout
10920 \begin_layout Standard
10921 To write an included chunk, we must detect any optional chunk arguments
10922  in parenthesis.
10923  Then we recurse calling 
10924 \begin_inset Flex Chunkref
10925 status collapsed
10927 \begin_layout Plain Layout
10928 write_chunk()
10929 \end_layout
10931 \end_inset
10934 \end_layout
10936 \begin_layout Chunk
10937 write-included-chunk
10938 \end_layout
10940 \begin_layout Standard
10941 \begin_inset listings
10942 inline false
10943 status open
10945 \begin_layout Plain Layout
10947 if (match(chunklet, "^([^
10948 \backslash
10950 \backslash
10952 \backslash
10954 \backslash
10955 (]*)
10956 \backslash
10958 \backslash
10959 ((.*)
10960 \backslash
10962 \backslash
10963 )$", chunklet_parts)) {
10964 \end_layout
10966 \begin_layout Plain Layout
10968   chunklet = chunklet_parts[1];
10969 \end_layout
10971 \begin_layout Plain Layout
10973   parse_chunk_args("", chunklet_parts[2], call_chunk_args, "(");
10974 \end_layout
10976 \begin_layout Plain Layout
10978   for (c in call_chunk_args) {
10979 \end_layout
10981 \begin_layout Plain Layout
10983     call_chunk_args[c] = expand_chunk_args(call_chunk_args[c], chunk_params,
10984  chunk_args);
10985 \end_layout
10987 \begin_layout Plain Layout
10989   }
10990 \end_layout
10992 \begin_layout Plain Layout
10994 } else {
10995 \end_layout
10997 \begin_layout Plain Layout
10999   split("", call_chunk_args);
11000 \end_layout
11002 \begin_layout Plain Layout
11005 \end_layout
11007 \begin_layout Plain Layout
11009 # update the transforms arrays
11010 \end_layout
11012 \begin_layout Plain Layout
11014 new_src = mode_escaper(context, s, r, src);
11015 \end_layout
11017 \begin_layout Plain Layout
11019 write_chunk_r(chunklet, context,
11020 \end_layout
11022 \begin_layout Plain Layout
11024             chunks[chunk_name, "part", part, "indent"] indent,
11025 \end_layout
11027 \begin_layout Plain Layout
11029             chunks[chunk_name, "part", part, "tail"],
11030 \end_layout
11032 \begin_layout Plain Layout
11034             chunk_path "
11035 \backslash
11036 n         " chunk_name,
11037 \end_layout
11039 \begin_layout Plain Layout
11041             call_chunk_args,
11042 \end_layout
11044 \begin_layout Plain Layout
11046                         s, r, new_src);
11047 \end_layout
11049 \end_inset
11052 \end_layout
11054 \begin_layout Standard
11055 Before we output a chunklet of lines, we first emit the file and line number
11056  if we have one, and if it is safe to do so.
11058 \end_layout
11060 \begin_layout Standard
11061 Chunklets are generally broken up by includes, so the start of a chunklet
11062  is a good place to do this.
11063  Then we output each line of the chunklet.
11064 \end_layout
11066 \begin_layout Standard
11067 When it is not safe, such as in the middle of a multi-line macro definition,
11069 \begin_inset Flex CharStyle:Code
11070 status collapsed
11072 \begin_layout Plain Layout
11073 lineno_suppressed
11074 \end_layout
11076 \end_inset
11078  is set to true, and in such a case we note that we want to emit the line
11079  statement when it is next safe.
11080 \end_layout
11082 \begin_layout Chunk
11083 write-chunklets
11084 \end_layout
11086 \begin_layout Standard
11087 \begin_inset listings
11088 inline false
11089 status open
11091 \begin_layout Plain Layout
11093 max_frag = chunks[chunklet, "line"];
11094 \end_layout
11096 \begin_layout Plain Layout
11098 for(frag = 1; frag <= max_frag; frag++) {
11099 \end_layout
11101 \begin_layout Plain Layout
11103   =<
11104 \backslash
11105 chunkref{write-file-line}>
11106 \end_layout
11108 \end_inset
11111 \end_layout
11113 \begin_layout Standard
11114 We then extract the chunklet text and expand any arguments.
11115 \end_layout
11117 \begin_layout Standard
11118 \begin_inset listings
11119 inline false
11120 status open
11122 \begin_layout Plain Layout
11124 \end_layout
11126 \begin_layout Plain Layout
11128   text = chunks[chunklet, frag];
11129 \end_layout
11131 \begin_layout Plain Layout
11134 \end_layout
11136 \begin_layout Plain Layout
11138   /* check params */
11139 \end_layout
11141 \begin_layout Plain Layout
11143   text = expand_chunk_args(text, chunk_params, chunk_args);
11144 \end_layout
11146 \end_inset
11149 \end_layout
11151 \begin_layout Standard
11152 If the text is a single newline (which we keep separate - see 
11153 \begin_inset CommandInset ref
11154 LatexCommand ref
11155 reference "lone-newline"
11157 \end_inset
11159 ) then we increment the line number.
11160  In the case where this is the last line of a chunk and it is not a top-level
11161  chunk we replace the newline with an empty string --- because the chunk
11162  that included this chunk will have the newline at the end of the line that
11163  included this chunk.
11164 \end_layout
11166 \begin_layout Standard
11167 We also note by 
11168 \begin_inset Flex CharStyle:Code
11169 status collapsed
11171 \begin_layout Plain Layout
11172 newline = 1
11173 \end_layout
11175 \end_inset
11177  that we have started a new line, so that indentation can be managed with
11178  the following piece of text.
11179 \end_layout
11181 \begin_layout Standard
11182 \begin_inset listings
11183 inline false
11184 status open
11186 \begin_layout Plain Layout
11188 \end_layout
11190 \begin_layout Plain Layout
11192  if (text == "
11193 \backslash
11194 n") {
11195 \end_layout
11197 \begin_layout Plain Layout
11199     lineno++;
11200 \end_layout
11202 \begin_layout Plain Layout
11204     if (part == max_part && frag == max_frag && length(chunk_path)) {
11205 \end_layout
11207 \begin_layout Plain Layout
11209       text = "";
11210 \end_layout
11212 \begin_layout Plain Layout
11214       break;
11215 \end_layout
11217 \begin_layout Plain Layout
11219     } else {
11220 \end_layout
11222 \begin_layout Plain Layout
11224       newline = 1;
11225 \end_layout
11227 \begin_layout Plain Layout
11229     }
11230 \end_layout
11232 \end_inset
11235 \end_layout
11237 \begin_layout Standard
11238 If this text does not represent a newline, but we see that we are the first
11239  piece of text on a newline, then we prefix our text with the current indent.
11240  NOTE: 
11241 \begin_inset Flex CharStyle:Code
11242 status collapsed
11244 \begin_layout Plain Layout
11245 newline
11246 \end_layout
11248 \end_inset
11250  is a global output-state variable, but the 
11251 \begin_inset Flex CharStyle:Code
11252 status collapsed
11254 \begin_layout Plain Layout
11255 indent
11256 \end_layout
11258 \end_inset
11260  is not.
11262 \end_layout
11264 \begin_layout Standard
11265 \begin_inset listings
11266 inline false
11267 status open
11269 \begin_layout Plain Layout
11271   } else if (length(text) || length(tail)) {
11272 \end_layout
11274 \begin_layout Plain Layout
11276     if (newline) text = indent text;
11277 \end_layout
11279 \begin_layout Plain Layout
11281     newline = 0;
11282 \end_layout
11284 \begin_layout Plain Layout
11286   }
11287 \end_layout
11289 \begin_layout Plain Layout
11291 \end_layout
11293 \end_inset
11296 \end_layout
11298 \begin_layout Standard
11299 Tail will soon no longer be relevant once mode-detection is in place.
11300 \end_layout
11302 \begin_layout Standard
11303 \begin_inset listings
11304 inline false
11305 status open
11307 \begin_layout Plain Layout
11309   text = text tail;
11310 \end_layout
11312 \begin_layout Plain Layout
11314   mode_tracker(context, text);
11315 \end_layout
11317 \begin_layout Plain Layout
11319   print transform_escape(s, r, text, src);
11320 \end_layout
11322 \end_inset
11325 \end_layout
11327 \begin_layout Standard
11328 If a line ends in a backslash --- suggesting continuation --- then we supress
11329  outputting file-line as it would probably break the continued lines.
11331 \end_layout
11333 \begin_layout Standard
11334 \begin_inset listings
11335 inline false
11336 status open
11338 \begin_layout Plain Layout
11340   if (linenos) {
11341 \end_layout
11343 \begin_layout Plain Layout
11345     lineno_suppressed = substr(lastline, length(lastline)) == "
11346 \backslash
11348 \backslash
11350 \end_layout
11352 \begin_layout Plain Layout
11354   }
11355 \end_layout
11357 \begin_layout Plain Layout
11360 \end_layout
11362 \end_inset
11365 \end_layout
11367 \begin_layout Standard
11368 Of course there is no point in actually outputting the source filename and
11369  line number (file-line) if they don't say anything new! We only need to
11370  emit them if they aren't what is expected, or if we we not able to emit
11371  one when they had changed.
11372 \end_layout
11374 \begin_layout Chunk
11375 write-file-line
11376 \end_layout
11378 \begin_layout Standard
11379 \begin_inset listings
11380 inline false
11381 status open
11383 \begin_layout Plain Layout
11385 if (newline && lineno_needed && ! lineno_suppressed) {
11386 \end_layout
11388 \begin_layout Plain Layout
11390   filename = a_filename;
11391 \end_layout
11393 \begin_layout Plain Layout
11395   lineno = a_lineno;
11396 \end_layout
11398 \begin_layout Plain Layout
11400   print "#line " lineno " 
11401 \backslash
11402 "" filename "
11403 \backslash
11405 \backslash
11407 \end_layout
11409 \begin_layout Plain Layout
11411   lineno_needed = 0;
11412 \end_layout
11414 \begin_layout Plain Layout
11417 \end_layout
11419 \end_inset
11422 \end_layout
11424 \begin_layout Standard
11425 We check if a new file-line is needed by checking if the source line matches
11426  what we (or a compiler) would expect.
11428 \end_layout
11430 \begin_layout Chunk
11431 check-source-jump
11432 \end_layout
11434 \begin_layout Standard
11435 \begin_inset listings
11436 inline false
11437 status open
11439 \begin_layout Plain Layout
11441 if (linenos && (chunk_name SUBSEP "part" SUBSEP part SUBSEP "FILENAME" in
11442  chunks)) {
11443 \end_layout
11445 \begin_layout Plain Layout
11447   a_filename = chunks[chunk_name, "part", part, "FILENAME"];
11448 \end_layout
11450 \begin_layout Plain Layout
11452   a_lineno = chunks[chunk_name, "part", part, "LINENO"];
11453 \end_layout
11455 \begin_layout Plain Layout
11457   if (a_filename != filename || a_lineno != lineno) {
11458 \end_layout
11460 \begin_layout Plain Layout
11462     lineno_needed++;
11463 \end_layout
11465 \begin_layout Plain Layout
11467   }
11468 \end_layout
11470 \begin_layout Plain Layout
11473 \end_layout
11475 \end_inset
11478 \end_layout
11480 \begin_layout Chapter
11481 Storing chunks
11482 \end_layout
11484 \begin_layout Standard
11485 Awk has pretty limited data structures, so we will use two main hashes.
11486  Uninterrupted sequences of a chunk will be stored in 
11487 \begin_inset Flex CharStyle:Code
11488 status collapsed
11490 \begin_layout Plain Layout
11491 chunklets
11492 \end_layout
11494 \end_inset
11496  and the chunklets used in a chunk will be stored in 
11497 \begin_inset Flex CharStyle:Code
11498 status collapsed
11500 \begin_layout Plain Layout
11501 chunks
11502 \end_layout
11504 \end_inset
11507 \end_layout
11509 \begin_layout Chunk
11510 constants
11511 \end_layout
11513 \begin_layout Standard
11514 \begin_inset listings
11515 inline false
11516 status open
11518 \begin_layout Plain Layout
11520 part_type_chunk=1;
11521 \end_layout
11523 \begin_layout Plain Layout
11525 SUBSEP=",";
11526 \end_layout
11528 \end_inset
11531 \end_layout
11533 \begin_layout Standard
11534 The 
11535 \begin_inset Flex CharStyle:Code
11536 status collapsed
11538 \begin_layout Plain Layout
11539 params
11540 \end_layout
11542 \end_inset
11544  mentioned are not chunk parameters for parameterized chunks, as mentioned
11545  in 
11546 \begin_inset CommandInset ref
11547 LatexCommand ref
11548 reference "cha:Chunk Arguments"
11550 \end_inset
11552 , but the lstlistings style parameters used in the 
11553 \begin_inset Flex CharStyle:Code
11554 status collapsed
11556 \begin_layout Plain Layout
11558 \backslash
11559 Chunk
11560 \end_layout
11562 \end_inset
11564  command
11565 \begin_inset Foot
11566 status collapsed
11568 \begin_layout Plain Layout
11569 The 
11570 \begin_inset Flex CharStyle:Code
11571 status collapsed
11573 \begin_layout Plain Layout
11574 params
11575 \end_layout
11577 \end_inset
11579  parameter is used to hold the parameters for parameterized chunks
11580 \end_layout
11582 \end_inset
11585 \end_layout
11587 \begin_layout Chunk
11588 chunk-storage-functions
11589 \end_layout
11591 \begin_layout Standard
11592 \begin_inset listings
11593 inline false
11594 status open
11596 \begin_layout Plain Layout
11598 function new_chunk(chunk_name, params,
11599 \end_layout
11601 \begin_layout Plain Layout
11603   # local vars
11604 \end_layout
11606 \begin_layout Plain Layout
11608   p, append )
11609 \end_layout
11611 \begin_layout Plain Layout
11614 \end_layout
11616 \begin_layout Plain Layout
11618   # HACK WHILE WE CHANGE TO ( ) for PARAM CHUNKS
11619 \end_layout
11621 \begin_layout Plain Layout
11623   gsub("
11624 \backslash
11626 \backslash
11628 \backslash
11630 \backslash
11631 )$", "", chunk_name);
11632 \end_layout
11634 \begin_layout Plain Layout
11636   if (! (chunk_name in chunk_names)) {
11637 \end_layout
11639 \begin_layout Plain Layout
11641     if (debug) print "New chunk " chunk_name;
11642 \end_layout
11644 \begin_layout Plain Layout
11646     chunk_names[chunk_name];
11647 \end_layout
11649 \begin_layout Plain Layout
11651     for (p in params) {
11652 \end_layout
11654 \begin_layout Plain Layout
11656       chunks[chunk_name, p] = params[p];
11657 \end_layout
11659 \begin_layout Plain Layout
11661     }
11662 \end_layout
11664 \begin_layout Plain Layout
11666     if ("append" in params) {
11667 \end_layout
11669 \begin_layout Plain Layout
11671       append=params["append"];
11672 \end_layout
11674 \begin_layout Plain Layout
11676       if (! (append in chunk_names)) {
11677 \end_layout
11679 \begin_layout Plain Layout
11681         warning("Chunk " chunk_name " is appended to chunk " append " which
11682  is not defined yet");
11683 \end_layout
11685 \begin_layout Plain Layout
11687         new_chunk(append);
11688 \end_layout
11690 \begin_layout Plain Layout
11692       }
11693 \end_layout
11695 \begin_layout Plain Layout
11697       chunk_include(append, chunk_name);
11698 \end_layout
11700 \begin_layout Plain Layout
11702       chunk_line(append, ORS);
11703 \end_layout
11705 \begin_layout Plain Layout
11707     }
11708 \end_layout
11710 \begin_layout Plain Layout
11712   }
11713 \end_layout
11715 \begin_layout Plain Layout
11717   active_chunk = chunk_name;
11718 \end_layout
11720 \begin_layout Plain Layout
11722   prime_chunk(chunk_name);
11723 \end_layout
11725 \begin_layout Plain Layout
11728 \end_layout
11730 \end_inset
11733 \end_layout
11735 \begin_layout Standard
11736 \begin_inset listings
11737 inline false
11738 status open
11740 \begin_layout Plain Layout
11742 \end_layout
11744 \begin_layout Plain Layout
11746 function prime_chunk(chunk_name)
11747 \end_layout
11749 \begin_layout Plain Layout
11752 \end_layout
11754 \begin_layout Plain Layout
11756   chunks[chunk_name, "part", ++chunks[chunk_name, "part"] ] = 
11757 \backslash
11759 \end_layout
11761 \begin_layout Plain Layout
11763          chunk_name SUBSEP "chunklet" SUBSEP "" ++chunks[chunk_name, "chunklet"]
11765 \end_layout
11767 \begin_layout Plain Layout
11769   chunks[chunk_name, "part", chunks[chunk_name, "part"], "FILENAME"] = FILENAME;
11770 \end_layout
11772 \begin_layout Plain Layout
11774   chunks[chunk_name, "part", chunks[chunk_name, "part"], "LINENO"] = FNR
11775  + 1;
11776 \end_layout
11778 \begin_layout Plain Layout
11781 \end_layout
11783 \begin_layout Plain Layout
11785 \end_layout
11787 \begin_layout Plain Layout
11789 function chunk_line(chunk_name, line){
11790 \end_layout
11792 \begin_layout Plain Layout
11794   chunks[chunk_name, "chunklet", chunks[chunk_name, "chunklet"],
11795 \end_layout
11797 \begin_layout Plain Layout
11799          ++chunks[chunk_name, "chunklet", chunks[chunk_name, "chunklet"],
11800  "line"]  ] = line;
11801 \end_layout
11803 \begin_layout Plain Layout
11806 \end_layout
11808 \begin_layout Plain Layout
11810 \end_layout
11812 \end_inset
11815 \end_layout
11817 \begin_layout Standard
11818 Chunk include represents a 
11819 \emph on
11820 chunkref
11821 \emph default
11822  statement, and stores the requirement to include another chunk.
11823  The parameter indent represents the quanity of literal text characters
11824  that preceded this 
11825 \emph on
11826 chunkref
11827 \emph default
11828  statement and therefore by how much additional lines of the included chunk
11829  should be indented.
11830 \end_layout
11832 \begin_layout Standard
11833 \begin_inset listings
11834 inline false
11835 status open
11837 \begin_layout Plain Layout
11839 function chunk_include(chunk_name, chunk_ref, indent, tail)
11840 \end_layout
11842 \begin_layout Plain Layout
11845 \end_layout
11847 \begin_layout Plain Layout
11849   chunks[chunk_name, "part", ++chunks[chunk_name, "part"] ] = chunk_ref;
11850 \end_layout
11852 \begin_layout Plain Layout
11854   chunks[chunk_name, "part", chunks[chunk_name, "part"], "type" ] = part_type_ch
11855 unk;
11856 \end_layout
11858 \begin_layout Plain Layout
11860   chunks[chunk_name, "part", chunks[chunk_name, "part"], "indent" ] = indent_str
11861 ing(indent);
11862 \end_layout
11864 \begin_layout Plain Layout
11866   chunks[chunk_name, "part", chunks[chunk_name, "part"], "tail" ] = tail;
11867 \end_layout
11869 \begin_layout Plain Layout
11871   prime_chunk(chunk_name);
11872 \end_layout
11874 \begin_layout Plain Layout
11877 \end_layout
11879 \begin_layout Plain Layout
11881 \end_layout
11883 \end_inset
11886 \end_layout
11888 \begin_layout Standard
11889 The indent is calculated by indent_string, which may in future convert some
11890  spaces into tab characters.
11891  This function works by generating a printf padded format string, like 
11892 \begin_inset Flex CharStyle:Code
11893 status collapsed
11895 \begin_layout Plain Layout
11896 %22s
11897 \end_layout
11899 \end_inset
11901  for an indent of 22, and then printing an empty string using that format.
11902 \end_layout
11904 \begin_layout Standard
11905 \begin_inset listings
11906 inline false
11907 status open
11909 \begin_layout Plain Layout
11911 function indent_string(indent) {
11912 \end_layout
11914 \begin_layout Plain Layout
11916   return sprintf("%" indent "s", "");
11917 \end_layout
11919 \begin_layout Plain Layout
11922 \end_layout
11924 \end_inset
11927 \end_layout
11929 \begin_layout Chapter
11930 \begin_inset CommandInset label
11931 LatexCommand label
11932 name "cha:getopt"
11934 \end_inset
11936 getopt
11937 \end_layout
11939 \begin_layout Standard
11940 I use Arnold Robbins public domain getopt (1993 revision).
11941  This is probably the same one that is covered in chapter 12 of 
11942 \begin_inset Quotes eld
11943 \end_inset
11945 Edition 3 of GAWK: Effective AWK Programming: A User's Guide for GNU Awk
11946 \begin_inset Quotes erd
11947 \end_inset
11949  but as that is licensed under the GNU Free Documentation License, Version
11950  1.3, which conflicts with the GPL3, I can't use it from there (or it's accompany
11951 ing explanations), so I do my best to explain how it works here.
11952 \end_layout
11954 \begin_layout Standard
11955 The getopt.awk header is:
11956 \end_layout
11958 \begin_layout Chunk
11959 getopt.awk-header,language=awk,morestring=[b]{/},morekeywords=else
11960 \end_layout
11962 \begin_layout Standard
11963 \begin_inset listings
11964 inline false
11965 status open
11967 \begin_layout Plain Layout
11969 # getopt.awk --- do C library getopt(3) function in awk
11970 \end_layout
11972 \begin_layout Plain Layout
11975 \end_layout
11977 \begin_layout Plain Layout
11979 # Arnold Robbins, arnold@skeeve.com, Public Domain
11980 \end_layout
11982 \begin_layout Plain Layout
11985 \end_layout
11987 \begin_layout Plain Layout
11989 # Initial version: March, 1991
11990 \end_layout
11992 \begin_layout Plain Layout
11994 # Revised: May, 1993
11995 \end_layout
11997 \begin_layout Plain Layout
11999 \end_layout
12001 \end_inset
12004 \end_layout
12006 \begin_layout Standard
12007 The provided explanation is:
12008 \end_layout
12010 \begin_layout Chunk
12011 getopt.awk-notes
12012 \end_layout
12014 \begin_layout Standard
12015 \begin_inset listings
12016 inline false
12017 status open
12019 \begin_layout Plain Layout
12021 # External variables:
12022 \end_layout
12024 \begin_layout Plain Layout
12026 #    Optind -- index in ARGV of first nonoption argument
12027 \end_layout
12029 \begin_layout Plain Layout
12031 #    Optarg -- string value of argument to current option
12032 \end_layout
12034 \begin_layout Plain Layout
12036 #    Opterr -- if nonzero, print our own diagnostic
12037 \end_layout
12039 \begin_layout Plain Layout
12041 #    Optopt -- current option letter
12042 \end_layout
12044 \begin_layout Plain Layout
12046 \end_layout
12048 \begin_layout Plain Layout
12050 # Returns:
12051 \end_layout
12053 \begin_layout Plain Layout
12055 #    -1     at end of options
12056 \end_layout
12058 \begin_layout Plain Layout
12060 #    ?      for unrecognized option
12061 \end_layout
12063 \begin_layout Plain Layout
12065 #    <c>    a character representing the current option
12066 \end_layout
12068 \begin_layout Plain Layout
12070 \end_layout
12072 \begin_layout Plain Layout
12074 # Private Data:
12075 \end_layout
12077 \begin_layout Plain Layout
12079 #    _opti  -- index in multi-flag option, e.g., -abc
12080 \end_layout
12082 \begin_layout Plain Layout
12084 \end_layout
12086 \end_inset
12089 \end_layout
12091 \begin_layout Standard
12092 The function follows.
12093  The final two parameters, 
12094 \begin_inset Flex CharStyle:Code
12095 status collapsed
12097 \begin_layout Plain Layout
12098 thisopt
12099 \end_layout
12101 \end_inset
12103  and 
12104 \begin_inset Flex CharStyle:Code
12105 status collapsed
12107 \begin_layout Plain Layout
12109 \end_layout
12111 \end_inset
12113  are local variables and not parameters --- as indicated by the multiple
12114  spaces preceding them.
12115  Awk doesn't care, the multiple spaces are a convention to help us humans.
12116 \end_layout
12118 \begin_layout Chunk
12119 getopt.awk-getopt()
12120 \end_layout
12122 \begin_layout Standard
12123 \begin_inset listings
12124 inline false
12125 status open
12127 \begin_layout Plain Layout
12129 function getopt(argc, argv, options,    thisopt, i)
12130 \end_layout
12132 \begin_layout Plain Layout
12135 \end_layout
12137 \begin_layout Plain Layout
12139     if (length(options) == 0)    # no options given
12140 \end_layout
12142 \begin_layout Plain Layout
12144         return -1
12145 \end_layout
12147 \begin_layout Plain Layout
12149     if (argv[Optind] == "--") {  # all done
12150 \end_layout
12152 \begin_layout Plain Layout
12154         Optind++
12155 \end_layout
12157 \begin_layout Plain Layout
12159         _opti = 0
12160 \end_layout
12162 \begin_layout Plain Layout
12164         return -1
12165 \end_layout
12167 \begin_layout Plain Layout
12169     } else if (argv[Optind] !~ /^-[^: 
12170 \backslash
12172 \backslash
12174 \backslash
12176 \backslash
12178 \backslash
12180 \backslash
12181 b]/) {
12182 \end_layout
12184 \begin_layout Plain Layout
12186         _opti = 0
12187 \end_layout
12189 \begin_layout Plain Layout
12191         return -1
12192 \end_layout
12194 \begin_layout Plain Layout
12196     }
12197 \end_layout
12199 \begin_layout Plain Layout
12201     if (_opti == 0)
12202 \end_layout
12204 \begin_layout Plain Layout
12206         _opti = 2
12207 \end_layout
12209 \begin_layout Plain Layout
12211     thisopt = substr(argv[Optind], _opti, 1)
12212 \end_layout
12214 \begin_layout Plain Layout
12216     Optopt = thisopt
12217 \end_layout
12219 \begin_layout Plain Layout
12221     i = index(options, thisopt)
12222 \end_layout
12224 \begin_layout Plain Layout
12226     if (i == 0) {
12227 \end_layout
12229 \begin_layout Plain Layout
12231         if (Opterr)
12232 \end_layout
12234 \begin_layout Plain Layout
12236             printf("%c -- invalid option
12237 \backslash
12239 \end_layout
12241 \begin_layout Plain Layout
12243                                   thisopt) > "/dev/stderr"
12244 \end_layout
12246 \begin_layout Plain Layout
12248         if (_opti >= length(argv[Optind])) {
12249 \end_layout
12251 \begin_layout Plain Layout
12253             Optind++
12254 \end_layout
12256 \begin_layout Plain Layout
12258             _opti = 0
12259 \end_layout
12261 \begin_layout Plain Layout
12263         } else
12264 \end_layout
12266 \begin_layout Plain Layout
12268             _opti++
12269 \end_layout
12271 \begin_layout Plain Layout
12273         return "?"
12274 \end_layout
12276 \begin_layout Plain Layout
12278     }
12279 \end_layout
12281 \end_inset
12284 \end_layout
12286 \begin_layout Standard
12287 At this point, the option has been found and we need to know if it takes
12288  any arguments.
12289 \end_layout
12291 \begin_layout Standard
12292 \begin_inset listings
12293 inline false
12294 status open
12296 \begin_layout Plain Layout
12298     if (substr(options, i + 1, 1) == ":") {
12299 \end_layout
12301 \begin_layout Plain Layout
12303         # get option argument
12304 \end_layout
12306 \begin_layout Plain Layout
12308         if (length(substr(argv[Optind], _opti + 1)) > 0)
12309 \end_layout
12311 \begin_layout Plain Layout
12313             Optarg = substr(argv[Optind], _opti + 1)
12314 \end_layout
12316 \begin_layout Plain Layout
12318         else
12319 \end_layout
12321 \begin_layout Plain Layout
12323             Optarg = argv[++Optind]
12324 \end_layout
12326 \begin_layout Plain Layout
12328         _opti = 0
12329 \end_layout
12331 \begin_layout Plain Layout
12333     } else
12334 \end_layout
12336 \begin_layout Plain Layout
12338         Optarg = ""
12339 \end_layout
12341 \begin_layout Plain Layout
12343     if (_opti == 0 || _opti >= length(argv[Optind])) {
12344 \end_layout
12346 \begin_layout Plain Layout
12348         Optind++
12349 \end_layout
12351 \begin_layout Plain Layout
12353         _opti = 0
12354 \end_layout
12356 \begin_layout Plain Layout
12358     } else
12359 \end_layout
12361 \begin_layout Plain Layout
12363         _opti++
12364 \end_layout
12366 \begin_layout Plain Layout
12368     return thisopt
12369 \end_layout
12371 \begin_layout Plain Layout
12374 \end_layout
12376 \end_inset
12378 A test program is built in, too
12379 \end_layout
12381 \begin_layout Chunk
12382 getopt.awk-begin
12383 \end_layout
12385 \begin_layout Standard
12386 \begin_inset listings
12387 inline false
12388 status open
12390 \begin_layout Plain Layout
12392 BEGIN {
12393 \end_layout
12395 \begin_layout Plain Layout
12397     Opterr = 1    # default is to diagnose
12398 \end_layout
12400 \begin_layout Plain Layout
12402     Optind = 1    # skip ARGV[0]
12403 \end_layout
12405 \begin_layout Plain Layout
12407     # test program
12408 \end_layout
12410 \begin_layout Plain Layout
12412     if (_getopt_test) {
12413 \end_layout
12415 \begin_layout Plain Layout
12417         while ((_go_c = getopt(ARGC, ARGV, "ab:cd")) != -1)
12418 \end_layout
12420 \begin_layout Plain Layout
12422             printf("c = <%c>, optarg = <%s>
12423 \backslash
12425 \end_layout
12427 \begin_layout Plain Layout
12429                                        _go_c, Optarg)
12430 \end_layout
12432 \begin_layout Plain Layout
12434         printf("non-option arguments:
12435 \backslash
12437 \end_layout
12439 \begin_layout Plain Layout
12441         for (; Optind < ARGC; Optind++)
12442 \end_layout
12444 \begin_layout Plain Layout
12446             printf("
12447 \backslash
12448 tARGV[%d] = <%s>
12449 \backslash
12451 \end_layout
12453 \begin_layout Plain Layout
12455                                     Optind, ARGV[Optind])
12456 \end_layout
12458 \begin_layout Plain Layout
12460     }
12461 \end_layout
12463 \begin_layout Plain Layout
12466 \end_layout
12468 \end_inset
12471 \end_layout
12473 \begin_layout Standard
12474 The entire getopt.awk is made out of these chunks in order
12475 \end_layout
12477 \begin_layout Chunk
12478 getopt.awk
12479 \end_layout
12481 \begin_layout Standard
12482 \begin_inset listings
12483 inline false
12484 status open
12486 \begin_layout Plain Layout
12489 \backslash
12490 chunkref{getopt.awk-header}>
12491 \end_layout
12493 \begin_layout Plain Layout
12495 \end_layout
12497 \begin_layout Plain Layout
12500 \backslash
12501 chunkref{getopt.awk-notes}>
12502 \end_layout
12504 \begin_layout Plain Layout
12507 \backslash
12508 chunkref{getopt.awk-getopt()}>
12509 \end_layout
12511 \begin_layout Plain Layout
12514 \backslash
12515 chunkref{getopt.awk-begin}>
12516 \end_layout
12518 \end_inset
12521 \end_layout
12523 \begin_layout Standard
12524 Although we only want the header and function:
12525 \end_layout
12527 \begin_layout Chunk
12528 getopt
12529 \end_layout
12531 \begin_layout Standard
12532 \begin_inset listings
12533 inline false
12534 status open
12536 \begin_layout Plain Layout
12538 # try: locate getopt.awk for the full original file
12539 \end_layout
12541 \begin_layout Plain Layout
12543 # as part of your standard awk installation
12544 \end_layout
12546 \begin_layout Plain Layout
12549 \backslash
12550 chunkref{getopt.awk-header}>
12551 \end_layout
12553 \begin_layout Plain Layout
12555 \end_layout
12557 \begin_layout Plain Layout
12560 \backslash
12561 chunkref{getopt.awk-getopt()}>
12562 \end_layout
12564 \end_inset
12567 \end_layout
12569 \begin_layout Chapter
12570 Newfangle LaTeX source code
12571 \end_layout
12573 \begin_layout Section
12574 newfangle module
12575 \end_layout
12577 \begin_layout Standard
12578 Here we define a Lyx .module file that makes it convenient to use LyX for
12579  writing such literate programs.
12580 \end_layout
12582 \begin_layout Standard
12583 This file 
12584 \begin_inset Flex CharStyle:Code
12585 status collapsed
12587 \begin_layout Plain Layout
12588 ./newfangle.module
12589 \end_layout
12591 \end_inset
12593  can be installed in your personal 
12594 \begin_inset Flex CharStyle:Code
12595 status collapsed
12597 \begin_layout Plain Layout
12598 .lyx/layouts folder
12599 \end_layout
12601 \end_inset
12604  You will need to Tools Reconfigure so that LyX notices it.
12605  It adds a new format Chunk, which should precede every listing and contain
12606  the chunk name.
12608 \end_layout
12610 \begin_layout Chunk
12611 ./newfangle.module,language=
12612 \end_layout
12614 \begin_layout Standard
12615 \begin_inset listings
12616 inline false
12617 status open
12619 \begin_layout Plain Layout
12622 \backslash
12623 DeclareLyXModule{Newfangle Literate Listings}
12624 \end_layout
12626 \begin_layout Plain Layout
12628 #DescriptionBegin
12629 \end_layout
12631 \begin_layout Plain Layout
12633 #  Newfangle literate listings allow one to write
12634 \end_layout
12636 \begin_layout Plain Layout
12638 #   literate programs after the fashion of noweb, but without having
12639 \end_layout
12641 \begin_layout Plain Layout
12643 #   to use noweave to generate the documentation.
12644  Instead the listings
12645 \end_layout
12647 \begin_layout Plain Layout
12649 #   package is extended in conjunction with the noweb package to implement
12650 \end_layout
12652 \begin_layout Plain Layout
12654 #   to code formating directly as latex.
12655 \end_layout
12657 \begin_layout Plain Layout
12659 #  The newfangle awk script
12660 \end_layout
12662 \begin_layout Plain Layout
12664 #DescriptionEnd
12665 \end_layout
12667 \begin_layout Plain Layout
12669 \end_layout
12671 \begin_layout Plain Layout
12673 Format 11
12674 \end_layout
12676 \begin_layout Plain Layout
12678 \end_layout
12680 \begin_layout Plain Layout
12682 AddToPreamble
12683 \end_layout
12685 \begin_layout Plain Layout
12688 \backslash
12689 chunkref{./newfangle.sty}>
12690 \end_layout
12692 \begin_layout Plain Layout
12694 EndPreamble
12695 \end_layout
12697 \begin_layout Plain Layout
12699 \end_layout
12701 \begin_layout Plain Layout
12704 \backslash
12705 chunkref{chunkstyle}>
12706 \end_layout
12708 \begin_layout Plain Layout
12710 \end_layout
12712 \begin_layout Plain Layout
12715 \backslash
12716 chunkref{chunkref}>
12717 \end_layout
12719 \end_inset
12722 \end_layout
12724 \begin_layout Subsection
12725 The Chunk style
12726 \end_layout
12728 \begin_layout Standard
12729 The purpose of the 
12730 \noun on
12731 chunk
12732 \noun default
12733  style is to make it easier for LyX users to provide the name to 
12734 \begin_inset Flex CharStyle:Code
12735 status collapsed
12737 \begin_layout Plain Layout
12739 \backslash
12740 lstlistings
12741 \end_layout
12743 \end_inset
12746  Normally this requires right-clicking on the listing, choosing settings,
12747  advanced, and then typing 
12748 \begin_inset Flex CharStyle:Code
12749 status collapsed
12751 \begin_layout Plain Layout
12752 name=chunk-name
12753 \end_layout
12755 \end_inset
12758  This has the further disadvantage that the name (and other options) are
12759  not generally visible during document editing.
12760 \end_layout
12762 \begin_layout Standard
12763 The chunk style is defined as a LaTeX command, so that all text on the same
12764  line is passed to the LaTeX command 
12765 \begin_inset Flex CharStyle:Code
12766 status collapsed
12768 \begin_layout Plain Layout
12769 Chunk
12770 \end_layout
12772 \end_inset
12775  This makes it easy to parse using 
12776 \begin_inset Flex CharStyle:Code
12777 status collapsed
12779 \begin_layout Plain Layout
12780 newfangle
12781 \end_layout
12783 \end_inset
12785 , and easy to pass these options on to the listings package.
12786  The first word in a chunk section should be the chunk name, and will have
12788 \begin_inset Flex CharStyle:Code
12789 status collapsed
12791 \begin_layout Plain Layout
12792 name=
12793 \end_layout
12795 \end_inset
12797  prepended to it.
12798  Any other words are accepted arguments to 
12799 \begin_inset Flex CharStyle:Code
12800 status collapsed
12802 \begin_layout Plain Layout
12804 \backslash
12805 lstset
12806 \end_layout
12808 \end_inset
12811 \end_layout
12813 \begin_layout Standard
12814 We set PassThru to 1 because the user is actually entering raw latex.
12815 \end_layout
12817 \begin_layout Chunk
12818 chunkstyle
12819 \end_layout
12821 \begin_layout Standard
12822 \begin_inset listings
12823 inline false
12824 status open
12826 \begin_layout Plain Layout
12828 Style Chunk
12829 \end_layout
12831 \begin_layout Plain Layout
12833   LatexType             Command
12834 \end_layout
12836 \begin_layout Plain Layout
12838   LatexName             Chunk
12839 \end_layout
12841 \begin_layout Plain Layout
12843   Margin                First_Dynamic
12844 \end_layout
12846 \begin_layout Plain Layout
12848   LeftMargin            Chunk:xxx
12849 \end_layout
12851 \begin_layout Plain Layout
12853   LabelSep              xx
12854 \end_layout
12856 \begin_layout Plain Layout
12858   LabelType             Static
12859 \end_layout
12861 \begin_layout Plain Layout
12863   LabelString           "Chunk:"
12864 \end_layout
12866 \begin_layout Plain Layout
12868   Align                 Left
12869 \end_layout
12871 \begin_layout Plain Layout
12873   PassThru              1
12874 \end_layout
12876 \begin_layout Plain Layout
12878 \end_layout
12880 \end_inset
12883 \end_layout
12885 \begin_layout Standard
12886 To make the label very visible we choose a larger font coloured red.
12887 \end_layout
12889 \begin_layout Standard
12890 \begin_inset listings
12891 inline false
12892 status open
12894 \begin_layout Plain Layout
12896   LabelFont
12897 \end_layout
12899 \begin_layout Plain Layout
12901     Family              Sans
12902 \end_layout
12904 \begin_layout Plain Layout
12906     Size                Large
12907 \end_layout
12909 \begin_layout Plain Layout
12911     Series              Bold
12912 \end_layout
12914 \begin_layout Plain Layout
12916     Shape               Italic
12917 \end_layout
12919 \begin_layout Plain Layout
12921     Color               red
12922 \end_layout
12924 \begin_layout Plain Layout
12926   EndFont
12927 \end_layout
12929 \begin_layout Plain Layout
12932 \end_layout
12934 \end_inset
12937 \end_layout
12939 \begin_layout Subsection
12940 The chunkref style
12941 \end_layout
12943 \begin_layout Standard
12944 We also define the Chunkref style which can be used to express cross references
12945  to chunks.
12946 \end_layout
12948 \begin_layout Chunk
12949 chunkref
12950 \end_layout
12952 \begin_layout Standard
12953 \begin_inset listings
12954 inline false
12955 status open
12957 \begin_layout Plain Layout
12959 InsetLayout Chunkref
12960 \end_layout
12962 \begin_layout Plain Layout
12964   LyxType               charstyle
12965 \end_layout
12967 \begin_layout Plain Layout
12969   LatexType             Command
12970 \end_layout
12972 \begin_layout Plain Layout
12974   LatexName             chunkref
12975 \end_layout
12977 \begin_layout Plain Layout
12979   PassThru              1
12980 \end_layout
12982 \begin_layout Plain Layout
12984   LabelFont             
12985 \end_layout
12987 \begin_layout Plain Layout
12989     Shape               Italic
12990 \end_layout
12992 \begin_layout Plain Layout
12994     Color               red
12995 \end_layout
12997 \begin_layout Plain Layout
12999   EndFont
13000 \end_layout
13002 \begin_layout Plain Layout
13005 \end_layout
13007 \end_inset
13010 \end_layout
13012 \begin_layout Section
13013 \begin_inset CommandInset label
13014 LatexCommand label
13015 name "sec:Latex-Macros"
13017 \end_inset
13019 Latex Macros
13020 \end_layout
13022 \begin_layout Standard
13023 We require the 
13024 \noun on
13025 listings
13026 \noun default
13028 \noun on
13029 noweb
13030 \noun default
13031  and 
13032 \noun on
13033 xargs
13034 \noun default
13035  packages.
13036  As noweb defines it's own 
13037 \begin_inset Flex CharStyle:Code
13038 status collapsed
13040 \begin_layout Plain Layout
13042 \backslash
13043 code
13044 \end_layout
13046 \end_inset
13048  environment, we re-define the one that LyX logical markup module expects
13049  here.
13050 \end_layout
13052 \begin_layout Chunk
13053 ./newfangle.sty,language=tex,basicstyle=
13054 \backslash
13055 ttfamily
13056 \end_layout
13058 \begin_layout Standard
13059 \begin_inset listings
13060 inline false
13061 status open
13063 \begin_layout Plain Layout
13066 \backslash
13067 usepackage{listings}%
13068 \end_layout
13070 \begin_layout Plain Layout
13073 \backslash
13074 usepackage{noweb}%
13075 \end_layout
13077 \begin_layout Plain Layout
13080 \backslash
13081 usepackage{xargs}%
13082 \end_layout
13084 \begin_layout Plain Layout
13087 \backslash
13088 renewcommand{
13089 \backslash
13090 code}[1]{
13091 \backslash
13092 texttt{#1}}%
13093 \end_layout
13095 \end_inset
13098 \end_layout
13100 \begin_layout Standard
13101 We also define a 
13102 \begin_inset Flex CharStyle:Code
13103 status collapsed
13105 \begin_layout Plain Layout
13106 CChunk
13107 \end_layout
13109 \end_inset
13111  macro, for use as: 
13112 \begin_inset Flex CharStyle:Code
13113 status collapsed
13115 \begin_layout Plain Layout
13117 \backslash
13118 begin{CChunk}
13119 \end_layout
13121 \end_inset
13123  which will need renaming to 
13124 \begin_inset Flex CharStyle:Code
13125 status collapsed
13127 \begin_layout Plain Layout
13129 \backslash
13130 begin{Chunk}
13131 \end_layout
13133 \end_inset
13135  when I can do this without clashing with 
13136 \begin_inset Flex CharStyle:Code
13137 status collapsed
13139 \begin_layout Plain Layout
13141 \backslash
13142 Chunk
13143 \end_layout
13145 \end_inset
13148 \end_layout
13150 \begin_layout Standard
13151 \begin_inset listings
13152 inline false
13153 status open
13155 \begin_layout Plain Layout
13158 \backslash
13159 lstnewenvironment{Chunk}{
13160 \backslash
13161 relax}{
13162 \backslash
13163 relax}%
13164 \end_layout
13166 \end_inset
13169 \end_layout
13171 \begin_layout Standard
13172 We also define a suitable 
13173 \begin_inset Flex CharStyle:Code
13174 status collapsed
13176 \begin_layout Plain Layout
13178 \backslash
13179 lstset
13180 \end_layout
13182 \end_inset
13184  of parameters that suit the literate programming style after the fashion
13185  of 
13186 \noun on
13187 noweave
13188 \noun default
13190 \end_layout
13192 \begin_layout Standard
13193 \begin_inset listings
13194 inline false
13195 status open
13197 \begin_layout Plain Layout
13200 \backslash
13201 lstset{numbers=left, stepnumber=5, numbersep=5pt,
13202 \end_layout
13204 \begin_layout Plain Layout
13206         breaklines=false,basicstyle=
13207 \backslash
13208 ttfamily,
13209 \end_layout
13211 \begin_layout Plain Layout
13213         numberstyle=
13214 \backslash
13215 tiny, language=C}%
13216 \end_layout
13218 \end_inset
13221 \end_layout
13223 \begin_layout Standard
13224 We also define a notangle-like mechanism for 
13225 \emph on
13226 escaping
13227 \emph default
13228  to LaTeX from the listing, and by which we can refer to other listings.
13229  We declare the 
13230 \begin_inset Flex CharStyle:Code
13231 status collapsed
13233 \begin_layout Plain Layout
13234 =<\SpecialChar \ldots{}
13236 \end_layout
13238 \end_inset
13240  sequence to contain LaTeX code, and include another like this chunk: 
13241 \begin_inset Flex CharStyle:Code
13242 status collapsed
13244 \begin_layout Plain Layout
13246 \backslash
13247 chunkref{chunkname}>
13248 \end_layout
13250 \end_inset
13253  However, because 
13254 \begin_inset Flex CharStyle:Code
13255 status collapsed
13257 \begin_layout Plain Layout
13258 =<\SpecialChar \ldots{}
13260 \end_layout
13262 \end_inset
13264  is already defined to contain LaTeX code for this document --- this is
13265  a 
13266 \noun on
13267 newfangle
13268 \noun default
13269  document after all --- the code fragment below effectively contains the
13270  LaTeX code: 
13271 \begin_inset Flex CharStyle:Code
13272 status collapsed
13274 \begin_layout Plain Layout
13276 \end_layout
13278 \end_inset
13281  To avoid problems with document generation, I had to declare an lstlistings
13282  property: 
13283 \begin_inset Flex CharStyle:Code
13284 status collapsed
13286 \begin_layout Plain Layout
13287 escapeinside={}
13288 \end_layout
13290 \end_inset
13292  for this listing only; which in LyX was done by right-clicking the listings
13293  inset, choosing 
13294 \begin_inset Flex CharStyle:Code
13295 status collapsed
13297 \begin_layout Plain Layout
13298 settings
13299 \end_layout
13301 \end_inset
13303 \SpecialChar \menuseparator
13305 \begin_inset Flex CharStyle:Code
13306 status collapsed
13308 \begin_layout Plain Layout
13309 advanced
13310 \end_layout
13312 \end_inset
13315 \end_layout
13317 \begin_layout Standard
13318 \begin_inset Note Note
13319 status collapsed
13321 \begin_layout Plain Layout
13322 =< isn't enjoyed literally here, in a listing when the escape sequence is
13323  already defined as shown...
13324  we need to somehow escape this representation...
13325 \end_layout
13327 \end_inset
13330 \end_layout
13332 \begin_layout Standard
13333 \begin_inset listings
13334 lstparams "escapeinside={}"
13335 inline false
13336 status open
13338 \begin_layout Plain Layout
13341 \backslash
13342 lstset{escapeinside={=<}{>}}%
13343 \end_layout
13345 \end_inset
13348 \end_layout
13350 \begin_layout Standard
13351 Although our macros will contain the @ symbol, they will be included in
13352  a 
13353 \begin_inset Flex CharStyle:Code
13354 status collapsed
13356 \begin_layout Plain Layout
13358 \backslash
13359 makeatletter
13360 \end_layout
13362 \end_inset
13364  section by LyX; however we keep the commented out 
13365 \begin_inset Flex CharStyle:Code
13366 status collapsed
13368 \begin_layout Plain Layout
13370 \backslash
13371 makeatletter
13372 \end_layout
13374 \end_inset
13376  as a reminder.
13377  The listings package likes to centre the titles, but noweb titles are specially
13378  formatted and must be left aligned.
13379  The simplest way to do this turned out to be by removing the definition
13380  of 
13381 \begin_inset Flex CharStyle:Code
13382 status collapsed
13384 \begin_layout Plain Layout
13386 \backslash
13387 lst@maketitle
13388 \end_layout
13390 \end_inset
13393  This may interact badly if other listings want a regular title or caption.
13394  We remember the old maketitle in case we need it.
13395 \end_layout
13397 \begin_layout Standard
13398 \begin_inset listings
13399 inline false
13400 status open
13402 \begin_layout Plain Layout
13405 \backslash
13406 makeatletter
13407 \end_layout
13409 \begin_layout Plain Layout
13411 %somehow re-defining maketitle gives us a left-aligned title
13412 \end_layout
13414 \begin_layout Plain Layout
13416 %which is extactly what our specially formatted title needs!
13417 \end_layout
13419 \begin_layout Plain Layout
13422 \backslash
13423 global
13424 \backslash
13426 \backslash
13427 newfangle@lst@maketitle
13428 \backslash
13429 lst@maketitle%
13430 \end_layout
13432 \begin_layout Plain Layout
13435 \backslash
13436 global
13437 \backslash
13439 \backslash
13440 lst@maketitle{}%
13441 \end_layout
13443 \end_inset
13446 \end_layout
13448 \begin_layout Subsection
13449 \begin_inset CommandInset label
13450 LatexCommand label
13451 name "sub:The-chunk-command"
13453 \end_inset
13455 The chunk command
13456 \end_layout
13458 \begin_layout Standard
13459 Our chunk command accepts one argument, and calls 
13460 \begin_inset Flex CharStyle:Code
13461 status collapsed
13463 \begin_layout Plain Layout
13465 \backslash
13466 ltset
13467 \end_layout
13469 \end_inset
13472  Although 
13473 \begin_inset Flex CharStyle:Code
13474 status collapsed
13476 \begin_layout Plain Layout
13478 \backslash
13479 ltset
13480 \end_layout
13482 \end_inset
13484  will note the name, this is erased when the next 
13485 \begin_inset Flex CharStyle:Code
13486 status collapsed
13488 \begin_layout Plain Layout
13490 \backslash
13491 lstlisting
13492 \end_layout
13494 \end_inset
13496  starts, so we make a note of this in 
13497 \begin_inset Flex CharStyle:Code
13498 status collapsed
13500 \begin_layout Plain Layout
13502 \backslash
13503 lst@chunkname
13504 \end_layout
13506 \end_inset
13508  and restore in in lstlistings Init hook.
13509 \end_layout
13511 \begin_layout Standard
13512 \begin_inset listings
13513 inline false
13514 status open
13516 \begin_layout Plain Layout
13519 \backslash
13521 \backslash
13522 Chunk#1{%
13523 \end_layout
13525 \begin_layout Plain Layout
13527   
13528 \backslash
13529 lstset{title={
13530 \backslash
13531 newfanglecaption},name=#1}%
13532 \end_layout
13534 \begin_layout Plain Layout
13536   
13537 \backslash
13538 global
13539 \backslash
13540 edef
13541 \backslash
13542 lst@chunkname{
13543 \backslash
13544 lst@intname}%
13545 \end_layout
13547 \begin_layout Plain Layout
13550 \end_layout
13552 \begin_layout Plain Layout
13555 \backslash
13557 \backslash
13558 lst@chunkname{
13559 \backslash
13560 empty}%
13561 \end_layout
13563 \end_inset
13566 \end_layout
13568 \begin_layout Subsubsection
13569 Chunk parameters
13570 \end_layout
13572 \begin_layout Standard
13573 Newfangle permits parameterized chunks, and requires the paramters to be
13574  specified as listings options.
13575  The newfangle script uses this, and although we don't do anything with
13576  these in the LaTeX code right now, we need to stop the listings package
13577  complaining.
13578 \end_layout
13580 \begin_layout Standard
13581 \begin_inset listings
13582 inline false
13583 status open
13585 \begin_layout Plain Layout
13588 \backslash
13589 lst@Key{params}
13590 \backslash
13591 relax{
13592 \backslash
13594 \backslash
13595 newfangle@chunk@params{#1}}%
13596 \end_layout
13598 \end_inset
13601 \end_layout
13603 \begin_layout Standard
13604 As it is common to define a chunk which then needs appending to another
13605  chunk, and annoying to have to declare a single line chunk to manage the
13606  include, we support an 
13607 \begin_inset Flex CharStyle:Code
13608 status collapsed
13610 \begin_layout Plain Layout
13611 append=
13612 \end_layout
13614 \end_inset
13616  option.
13618 \end_layout
13620 \begin_layout Standard
13621 \begin_inset listings
13622 inline false
13623 status open
13625 \begin_layout Plain Layout
13628 \backslash
13629 lst@Key{append}
13630 \backslash
13631 relax{
13632 \backslash
13634 \backslash
13635 newfangle@chunk@append{#1}}%
13636 \end_layout
13638 \end_inset
13641 \end_layout
13643 \begin_layout Subsection
13644 The noweb styled caption
13645 \end_layout
13647 \begin_layout Standard
13648 We define a public macro 
13649 \begin_inset Flex CharStyle:Code
13650 status collapsed
13652 \begin_layout Plain Layout
13654 \backslash
13655 newfanglecaption
13656 \end_layout
13658 \end_inset
13660  which can be set as a regular title.
13661  By means of 
13662 \begin_inset Flex CharStyle:Code
13663 status collapsed
13665 \begin_layout Plain Layout
13667 \backslash
13668 protect
13669 \end_layout
13671 \end_inset
13673 , It expands to 
13674 \begin_inset Flex CharStyle:Code
13675 status collapsed
13677 \begin_layout Plain Layout
13679 \backslash
13680 newfangle@caption
13681 \end_layout
13683 \end_inset
13685  at the appriate time when the caption is emitted.
13686 \end_layout
13688 \begin_layout Standard
13689 \begin_inset listings
13690 inline false
13691 status open
13693 \begin_layout Plain Layout
13696 \backslash
13698 \backslash
13699 newfanglecaption{
13700 \backslash
13701 protect
13702 \backslash
13703 newfangle@caption}%
13704 \end_layout
13706 \end_inset
13709 \end_layout
13711 \begin_layout Standard
13712 \begin_inset Float figure
13713 placement H
13714 wide false
13715 sideways false
13716 status collapsed
13718 \begin_layout Plain Layout
13719 \begin_inset Box Boxed
13720 position "t"
13721 hor_pos "c"
13722 has_inner_box 1
13723 inner_pos "t"
13724 use_parbox 0
13725 width "100col%"
13726 special "none"
13727 height "1in"
13728 height_special "totalheight"
13729 status open
13731 \begin_layout Plain Layout
13733 \begin_inset space \qquad{}
13734 \end_inset
13737 \shape italic
13738 some-chunk
13739 \shape default
13740  19b⟩
13741 \begin_inset Formula $\equiv+$
13742 \end_inset
13745 \begin_inset space \qquad{}
13746 \end_inset
13749 \begin_inset space \qquad{}
13750 \end_inset
13753 \begin_inset space \qquad{}
13754 \end_inset
13757 \begin_inset Formula $\triangleleft$
13758 \end_inset
13761 \begin_inset space \quad{}
13762 \end_inset
13765 \begin_inset Formula $\triangleright$
13766 \end_inset
13769 \end_layout
13771 \begin_layout Plain Layout
13773 \size footnotesize
13774 In this example, the current chunk is 22c, and therefore the third chunk
13775  on page 22.
13776 \end_layout
13778 \begin_layout Plain Layout
13780 \size footnotesize
13781 It's name is 
13782 \emph on
13783 some-chunk
13784 \emph default
13787 \end_layout
13789 \begin_layout Plain Layout
13791 \size footnotesize
13792 The first chunk with this name (19b) occurs as the second chunk on page
13793  19.
13794 \end_layout
13796 \begin_layout Plain Layout
13798 \size footnotesize
13799 The previous chunk (22d) with the same name is the second chunk on page
13800  22.
13801 \end_layout
13803 \begin_layout Plain Layout
13805 \size footnotesize
13806 The next chunk (24d) is the fourth chunk on page 24.
13807 \end_layout
13809 \begin_layout Plain Layout
13810 \begin_inset Caption
13812 \begin_layout Plain Layout
13813 noweb heading
13814 \end_layout
13816 \end_inset
13819 \end_layout
13821 \end_inset
13824 \end_layout
13826 \end_inset
13828 The general noweb output format compactly identifies the current chunk,
13829  and references to the first chunk, and the previous and next chunks that
13830  have the same name.
13832 \end_layout
13834 \begin_layout Standard
13835 This means that we need to keep a counter for each chunk-name, that we use
13836  to count chunks of the same name.
13838 \end_layout
13840 \begin_layout Subsection
13841 The chunk counter
13842 \end_layout
13844 \begin_layout Standard
13845 It would be natural to have a counter for each chunk name, but TeX would
13846  soon run out of counters
13847 \begin_inset Foot
13848 status collapsed
13850 \begin_layout Plain Layout
13851 \SpecialChar \ldots{}
13852 soon 
13853 \emph on
13855 \emph default
13856  run out of counters and so I had to re-write the LaTeX macros to share
13857  a counter as described here
13858 \end_layout
13860 \end_inset
13862 , so we have one counter which we save at the end of a chunk and restore
13863  at the beginning of a chunk.
13864 \end_layout
13866 \begin_layout Standard
13867 \begin_inset listings
13868 inline false
13869 status open
13871 \begin_layout Plain Layout
13874 \backslash
13875 newcounter{newfangle@chunkcounter}%
13876 \end_layout
13878 \end_inset
13881 \end_layout
13883 \begin_layout Standard
13884 We construct the name of this variable to store the counter to be the text
13886 \begin_inset Flex CharStyle:Code
13887 status collapsed
13889 \begin_layout Plain Layout
13890 lst-chunk-
13891 \end_layout
13893 \end_inset
13895  prefixed onto the chunks own name, and store it in 
13896 \begin_inset Flex CharStyle:Code
13897 status collapsed
13899 \begin_layout Plain Layout
13901 \backslash
13902 chunkcount
13903 \end_layout
13905 \end_inset
13909 \end_layout
13911 \begin_layout Standard
13912 We save the counter like this:
13913 \end_layout
13915 \begin_layout Chunk
13916 save-counter
13917 \end_layout
13919 \begin_layout Standard
13920 \begin_inset listings
13921 inline false
13922 status open
13924 \begin_layout Plain Layout
13927 \backslash
13928 global
13929 \backslash
13930 expandafter
13931 \backslash
13932 edef
13933 \backslash
13934 csname 
13935 \backslash
13936 chunkcount
13937 \backslash
13938 endcsname{
13939 \backslash
13940 arabic{newfangle@chunkcounter}}%
13941 \end_layout
13943 \end_inset
13946 \end_layout
13948 \begin_layout Standard
13949 and restore the counter like this:
13950 \end_layout
13952 \begin_layout Chunk
13953 restore-counter
13954 \end_layout
13956 \begin_layout Standard
13957 \begin_inset listings
13958 inline false
13959 status open
13961 \begin_layout Plain Layout
13964 \backslash
13965 setcounter{newfangle@chunkcounter}{
13966 \backslash
13967 csname 
13968 \backslash
13969 chunkcount
13970 \backslash
13971 endcsname}%
13972 \end_layout
13974 \end_inset
13977 \end_layout
13979 \begin_layout Chunk
13980 ./newfangle.sty
13981 \end_layout
13983 \begin_layout Standard
13984 If there does not already exist a variable whose name is stored in 
13985 \begin_inset Flex CharStyle:Code
13986 status collapsed
13988 \begin_layout Plain Layout
13990 \backslash
13991 chunkcount
13992 \end_layout
13994 \end_inset
13996 , then we know we are the first chunk with this name, and then define a
13997  counter.
13999 \end_layout
14001 \begin_layout Standard
14002 Although chunks of the same name share a common counter, they must still
14003  be distinguished.
14004  We use is the internal name of the listing, suffixed by the counter value.
14005  So the first chunk might be 
14006 \begin_inset Flex CharStyle:Code
14007 status collapsed
14009 \begin_layout Plain Layout
14010 something-1
14011 \end_layout
14013 \end_inset
14015  and the second chunk be 
14016 \begin_inset Flex CharStyle:Code
14017 status collapsed
14019 \begin_layout Plain Layout
14020 something-2
14021 \end_layout
14023 \end_inset
14025 , etc.
14026 \end_layout
14028 \begin_layout Standard
14029 We also calculate the name of the previous chunk if we can (before we increment
14030  the chunk counter).
14031  If this is the first chunk of that name, then 
14032 \begin_inset Flex CharStyle:Code
14033 status collapsed
14035 \begin_layout Plain Layout
14037 \backslash
14038 prevchunkname
14039 \end_layout
14041 \end_inset
14043  is set to 
14044 \begin_inset Flex CharStyle:Code
14045 status collapsed
14047 \begin_layout Plain Layout
14049 \backslash
14050 relax
14051 \end_layout
14053 \end_inset
14055  which the noweb package will interpret as not existing.
14056 \end_layout
14058 \begin_layout Standard
14059 \begin_inset listings
14060 inline false
14061 status open
14063 \begin_layout Plain Layout
14066 \backslash
14068 \backslash
14069 newfangle@caption{%
14070 \end_layout
14072 \begin_layout Plain Layout
14074   
14075 \backslash
14076 edef
14077 \backslash
14078 chunkcount{lst-chunk-
14079 \backslash
14080 lst@intname}%
14081 \end_layout
14083 \begin_layout Plain Layout
14085   
14086 \backslash
14087 @ifundefined{
14088 \backslash
14089 chunkcount}{%
14090 \end_layout
14092 \begin_layout Plain Layout
14094     
14095 \backslash
14096 expandafter
14097 \backslash
14098 gdef
14099 \backslash
14100 csname 
14101 \backslash
14102 chunkcount
14103 \backslash
14104 endcsname{0}%
14105 \end_layout
14107 \begin_layout Plain Layout
14109     
14110 \backslash
14111 setcounter{newfangle@chunkcounter}{
14112 \backslash
14113 csname 
14114 \backslash
14115 chunkcount
14116 \backslash
14117 endcsname}%
14118 \end_layout
14120 \begin_layout Plain Layout
14122     
14123 \backslash
14125 \backslash
14126 prevchunkname
14127 \backslash
14128 relax%
14129 \end_layout
14131 \begin_layout Plain Layout
14133   }{%
14134 \end_layout
14136 \begin_layout Plain Layout
14138     
14139 \backslash
14140 setcounter{newfangle@chunkcounter}{
14141 \backslash
14142 csname 
14143 \backslash
14144 chunkcount
14145 \backslash
14146 endcsname}%
14147 \end_layout
14149 \begin_layout Plain Layout
14151     
14152 \backslash
14153 edef
14154 \backslash
14155 prevchunkname{
14156 \backslash
14157 lst@intname-
14158 \backslash
14159 arabic{newfangle@chunkcounter}}%
14160 \end_layout
14162 \begin_layout Plain Layout
14164   }%
14165 \end_layout
14167 \end_inset
14170 \end_layout
14172 \begin_layout Standard
14173 After incrementing the chunk counter, we then define the name of this chunk,
14174  as well as the name of the first chunk.
14175 \end_layout
14177 \begin_layout Standard
14178 \begin_inset listings
14179 inline false
14180 status open
14182 \begin_layout Plain Layout
14184   
14185 \backslash
14186 addtocounter{newfangle@chunkcounter}{1}%
14187 \end_layout
14189 \begin_layout Plain Layout
14191   
14192 \backslash
14193 global
14194 \backslash
14195 expandafter
14196 \backslash
14197 edef
14198 \backslash
14199 csname 
14200 \backslash
14201 chunkcount
14202 \backslash
14203 endcsname{
14204 \backslash
14205 arabic{newfangle@chunkcounter}}%
14206 \end_layout
14208 \begin_layout Plain Layout
14210   
14211 \backslash
14212 edef
14213 \backslash
14214 chunkname{
14215 \backslash
14216 lst@intname-
14217 \backslash
14218 arabic{newfangle@chunkcounter}}%
14219 \end_layout
14221 \begin_layout Plain Layout
14223   
14224 \backslash
14225 edef
14226 \backslash
14227 firstchunkname{
14228 \backslash
14229 lst@intname-1}%
14230 \end_layout
14232 \end_inset
14235 \end_layout
14237 \begin_layout Standard
14238 We now need to calculate the name of the next chunk.
14239  We do this by temporarily skipping the counter on by one; however there
14240  may not actually be another chunk with this name! We detect this by also
14241  defining a label for each chunk based on the chunkname.
14242  If there is a next chunkname then it will define a label with that name.
14243  As labels are persistent, we can at least tell the second time LaTeX is
14244  run.
14245  If we don't find such a defined label then we define 
14246 \begin_inset Flex CharStyle:Code
14247 status collapsed
14249 \begin_layout Plain Layout
14251 \backslash
14252 nextchunkname
14253 \end_layout
14255 \end_inset
14257  to 
14258 \begin_inset Flex CharStyle:Code
14259 status collapsed
14261 \begin_layout Plain Layout
14263 \backslash
14264 relax
14265 \end_layout
14267 \end_inset
14270 \end_layout
14272 \begin_layout Standard
14273 \begin_inset listings
14274 inline false
14275 status open
14277 \begin_layout Plain Layout
14279   
14280 \backslash
14281 addtocounter{newfangle@chunkcounter}{1}%
14282 \end_layout
14284 \begin_layout Plain Layout
14286   
14287 \backslash
14288 edef
14289 \backslash
14290 nextchunkname{
14291 \backslash
14292 lst@intname-
14293 \backslash
14294 arabic{newfangle@chunkcounter}}%
14295 \end_layout
14297 \begin_layout Plain Layout
14299   
14300 \backslash
14301 @ifundefined{r@label-
14302 \backslash
14303 nextchunkname}{
14304 \backslash
14306 \backslash
14307 nextchunkname
14308 \backslash
14309 relax}{}%
14310 \end_layout
14312 \end_inset
14315 \end_layout
14317 \begin_layout Standard
14318 The noweb package requires that we define a 
14319 \begin_inset Flex CharStyle:Code
14320 status collapsed
14322 \begin_layout Plain Layout
14324 \backslash
14325 sublabel
14326 \end_layout
14328 \end_inset
14330  for every chunk, with a unique name, which is then used to print out it's
14331  navigation hints.
14332 \end_layout
14334 \begin_layout Standard
14335 We also define a regular label for this chunk, as was mentioned above when
14336  we calculated 
14337 \begin_inset Flex CharStyle:Code
14338 status collapsed
14340 \begin_layout Plain Layout
14342 \backslash
14343 nextchunkname
14344 \end_layout
14346 \end_inset
14349  This requires LaTeX to be run at least twice after new chunk sections are
14350  added --- but noweb requried that anyway.
14351 \end_layout
14353 \begin_layout Standard
14354 \begin_inset listings
14355 inline false
14356 status open
14358 \begin_layout Plain Layout
14360   
14361 \backslash
14362 sublabel{
14363 \backslash
14364 chunkname}%
14365 \end_layout
14367 \begin_layout Plain Layout
14369 % define this label for every chunk instance, so we
14370 \end_layout
14372 \begin_layout Plain Layout
14374 % can tell when we are the last chunk of this name
14375 \end_layout
14377 \begin_layout Plain Layout
14379   
14380 \backslash
14381 label{label-
14382 \backslash
14383 chunkname}%
14384 \end_layout
14386 \end_inset
14389 \end_layout
14391 \begin_layout Standard
14392 We also try and add the chunk to the list of listings, but I'm afraid we
14393  don't do very well.
14394  We want each chunk name listing once, with all of it's references.
14395 \end_layout
14397 \begin_layout Standard
14398 \begin_inset listings
14399 inline false
14400 status open
14402 \begin_layout Plain Layout
14404   
14405 \backslash
14406 addcontentsline{lol}{lstlisting}{
14407 \backslash
14408 lst@name~[
14409 \backslash
14410 protect
14411 \backslash
14412 subpageref{
14413 \backslash
14414 chunkname}]}%
14415 \end_layout
14417 \end_inset
14420 \end_layout
14422 \begin_layout Standard
14423 We then call the noweb output macros in the same way that noweave generates
14424  them, except that we don't need to call 
14425 \begin_inset Flex CharStyle:Code
14426 status collapsed
14428 \begin_layout Plain Layout
14430 \backslash
14431 nwstartdeflinemarkup
14432 \end_layout
14434 \end_inset
14436  or 
14437 \begin_inset Flex CharStyle:Code
14438 status collapsed
14440 \begin_layout Plain Layout
14442 \backslash
14443 nwenddeflinemarkup
14444 \end_layout
14446 \end_inset
14448  -- and if we do it messes up the output somewhat.
14449 \end_layout
14451 \begin_layout Standard
14452 \begin_inset listings
14453 inline false
14454 status open
14456 \begin_layout Plain Layout
14458   
14459 \backslash
14460 nwmargintag{%
14461 \end_layout
14463 \begin_layout Plain Layout
14465     {%
14466 \end_layout
14468 \begin_layout Plain Layout
14470       
14471 \backslash
14472 nwtagstyle{}%
14473 \end_layout
14475 \begin_layout Plain Layout
14477       
14478 \backslash
14479 subpageref{
14480 \backslash
14481 chunkname}%
14482 \end_layout
14484 \begin_layout Plain Layout
14486     }%
14487 \end_layout
14489 \begin_layout Plain Layout
14491   }%
14492 \end_layout
14494 \begin_layout Plain Layout
14497 \end_layout
14499 \begin_layout Plain Layout
14501   
14502 \backslash
14503 moddef{%
14504 \end_layout
14506 \begin_layout Plain Layout
14508     {
14509 \backslash
14510 lst@name}%
14511 \end_layout
14513 \begin_layout Plain Layout
14515     {%
14516 \end_layout
14518 \begin_layout Plain Layout
14520       
14521 \backslash
14522 nwtagstyle{}
14523 \backslash
14525 \end_layout
14527 \begin_layout Plain Layout
14529       
14530 \backslash
14531 @ifundefined{newfangle@chunk@params}{}{%
14532 \end_layout
14534 \begin_layout Plain Layout
14536         (
14537 \backslash
14538 newfangle@chunk@params)%
14539 \end_layout
14541 \begin_layout Plain Layout
14543       }%
14544 \end_layout
14546 \begin_layout Plain Layout
14548       [
14549 \backslash
14550 csname 
14551 \backslash
14552 chunkcount
14553 \backslash
14554 endcsname]~%
14555 \end_layout
14557 \begin_layout Plain Layout
14559       
14560 \backslash
14561 subpageref{
14562 \backslash
14563 firstchunkname}%
14564 \end_layout
14566 \begin_layout Plain Layout
14568     }%
14569 \end_layout
14571 \begin_layout Plain Layout
14573     
14574 \backslash
14575 @ifundefined{newfangle@chunk@append}{}{%
14576 \end_layout
14578 \begin_layout Plain Layout
14580     
14581 \backslash
14582 ifx{}
14583 \backslash
14584 newfangle@chunk@append{x}
14585 \backslash
14586 else%
14587 \end_layout
14589 \begin_layout Plain Layout
14591         ,~add~to~
14592 \backslash
14593 newfangle@chunk@append%
14594 \end_layout
14596 \begin_layout Plain Layout
14598     
14599 \backslash
14601 \end_layout
14603 \begin_layout Plain Layout
14605     }%
14606 \end_layout
14608 \begin_layout Plain Layout
14611 \backslash
14612 global
14613 \backslash
14615 \backslash
14616 newfangle@chunk@append{}%
14617 \end_layout
14619 \begin_layout Plain Layout
14622 \backslash
14623 lstset{append=x}%
14624 \end_layout
14626 \begin_layout Plain Layout
14628   }%
14629 \end_layout
14631 \begin_layout Plain Layout
14634 \end_layout
14636 \begin_layout Plain Layout
14638   
14639 \backslash
14641 \backslash
14642 relax
14643 \backslash
14644 prevchunkname
14645 \backslash
14646 endmoddef
14647 \backslash
14648 else
14649 \backslash
14650 plusendmoddef
14651 \backslash
14653 \end_layout
14655 \begin_layout Plain Layout
14657 %  
14658 \backslash
14659 nwstartdeflinemarkup%
14660 \end_layout
14662 \begin_layout Plain Layout
14664   
14665 \backslash
14666 nwprevnextdefs{
14667 \backslash
14668 prevchunkname}{
14669 \backslash
14670 nextchunkname}%
14671 \end_layout
14673 \begin_layout Plain Layout
14675 %  
14676 \backslash
14677 nwenddeflinemarkup%
14678 \end_layout
14680 \begin_layout Plain Layout
14683 \end_layout
14685 \end_inset
14688 \end_layout
14690 \begin_layout Standard
14691 Originally this was developed as a 
14692 \begin_inset Flex CharStyle:Code
14693 status collapsed
14695 \begin_layout Plain Layout
14696 listings
14697 \end_layout
14699 \end_inset
14701  aspect, in the Init hook, but it was found easier to affect the title without
14702  using a hook --- 
14703 \begin_inset Flex CharStyle:Code
14704 status collapsed
14706 \begin_layout Plain Layout
14708 \backslash
14709 lst@AddToHookExe{PreSet}
14710 \end_layout
14712 \end_inset
14714  is still required to set the listings name to the name passed to the 
14715 \begin_inset Flex CharStyle:Code
14716 status collapsed
14718 \begin_layout Plain Layout
14720 \backslash
14721 Chunk
14722 \end_layout
14724 \end_inset
14726  command, though.
14727 \end_layout
14729 \begin_layout Standard
14730 \begin_inset listings
14731 inline false
14732 status open
14734 \begin_layout Plain Layout
14737 \backslash
14738 lst@BeginAspect{newfangle}
14739 \end_layout
14741 \begin_layout Plain Layout
14744 \backslash
14745 lst@Key{newfangle}{true}[t]{
14746 \backslash
14747 lstKV@SetIf{#1}{true}}
14748 \end_layout
14750 \begin_layout Plain Layout
14753 \backslash
14754 lst@AddToHookExe{PreSet}{
14755 \backslash
14756 global
14757 \backslash
14759 \backslash
14760 lst@intname
14761 \backslash
14762 lst@chunkname}
14763 \end_layout
14765 \begin_layout Plain Layout
14768 \backslash
14769 lst@AddToHook{Init}{}%
14770 \backslash
14771 newfangle@caption}
14772 \end_layout
14774 \begin_layout Plain Layout
14777 \backslash
14778 lst@EndAspect
14779 \end_layout
14781 \end_inset
14784 \end_layout
14786 \begin_layout Subsection
14787 Cross references
14788 \end_layout
14790 \begin_layout Standard
14791 We define the 
14792 \backslash
14793 chunkref command which makes it easy to generate visual references to different
14794  code chunks, e.g.
14795 \end_layout
14797 \begin_layout Standard
14798 \begin_inset Tabular
14799 <lyxtabular version="3" rows="4" columns="2">
14800 <features>
14801 <column alignment="center" valignment="top" width="0">
14802 <column alignment="center" valignment="top" width="0">
14803 <row>
14804 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
14805 \begin_inset Text
14807 \begin_layout Plain Layout
14808 Macro
14809 \end_layout
14811 \end_inset
14812 </cell>
14813 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
14814 \begin_inset Text
14816 \begin_layout Plain Layout
14817 Appearance
14818 \end_layout
14820 \end_inset
14821 </cell>
14822 </row>
14823 <row>
14824 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
14825 \begin_inset Text
14827 \begin_layout Plain Layout
14829 \backslash
14830 chunkref{preamble}
14831 \end_layout
14833 \end_inset
14834 </cell>
14835 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
14836 \begin_inset Text
14838 \begin_layout Plain Layout
14839 \begin_inset ERT
14840 status open
14842 \begin_layout Plain Layout
14845 \backslash
14846 chunkref{preamble}
14847 \end_layout
14849 \end_inset
14852 \end_layout
14854 \end_inset
14855 </cell>
14856 </row>
14857 <row>
14858 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
14859 \begin_inset Text
14861 \begin_layout Plain Layout
14863 \backslash
14864 chunkref[3]{preamble}
14865 \end_layout
14867 \end_inset
14868 </cell>
14869 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
14870 \begin_inset Text
14872 \begin_layout Plain Layout
14873 \begin_inset ERT
14874 status open
14876 \begin_layout Plain Layout
14879 \backslash
14880 chunkref[3]{preamble}
14881 \end_layout
14883 \end_inset
14886 \end_layout
14888 \end_inset
14889 </cell>
14890 </row>
14891 <row>
14892 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
14893 \begin_inset Text
14895 \begin_layout Plain Layout
14897 \backslash
14898 chunkref{preamble}[arg1, arg2]
14899 \end_layout
14901 \end_inset
14902 </cell>
14903 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
14904 \begin_inset Text
14906 \begin_layout Plain Layout
14907 \begin_inset ERT
14908 status open
14910 \begin_layout Plain Layout
14913 \backslash
14914 chunkref{preamble}[arg1, arg2]
14915 \end_layout
14917 \end_inset
14920 \end_layout
14922 \end_inset
14923 </cell>
14924 </row>
14925 </lyxtabular>
14927 \end_inset
14930 \end_layout
14932 \begin_layout Standard
14933 Chunkref can also be used within a code chunk to include another code chunk.
14934  The third optional parameter to chunkref is a comma sepatarated list of
14935  arguments, which will replace defined parameters in the chunkref.
14936 \begin_inset Note Note
14937 status open
14939 \begin_layout Plain Layout
14940 Darn it, if I have: =<
14941 \backslash
14942 chunkref{new-mode-tracker}[{chunks[chunk_name, "language"]},{mode}]> the
14943  inner braces (inside [ ]) cause _ to signify subscript even though we have
14944  lst@ReplaceIn
14945 \end_layout
14947 \end_inset
14950 \end_layout
14952 \begin_layout Standard
14953 \begin_inset listings
14954 inline false
14955 status open
14957 \begin_layout Plain Layout
14960 \backslash
14962 \backslash
14963 chunkref@args#1,{%
14964 \end_layout
14966 \begin_layout Plain Layout
14968   
14969 \backslash
14971 \backslash
14972 arg{#1}%
14973 \end_layout
14975 \begin_layout Plain Layout
14977   
14978 \backslash
14979 lst@ReplaceIn
14980 \backslash
14982 \backslash
14983 lst@filenamerpl%
14984 \end_layout
14986 \begin_layout Plain Layout
14988   
14989 \backslash
14990 arg%
14991 \end_layout
14993 \begin_layout Plain Layout
14995   
14996 \backslash
14997 @ifnextchar){
14998 \backslash
14999 relax}{, 
15000 \backslash
15001 chunkref@args}%
15002 \end_layout
15004 \begin_layout Plain Layout
15007 \end_layout
15009 \begin_layout Plain Layout
15012 \backslash
15013 newcommand
15014 \backslash
15015 chunkref[2][0]{%
15016 \end_layout
15018 \begin_layout Plain Layout
15020   
15021 \backslash
15022 @ifnextchar({
15023 \backslash
15024 chunkref@i{#1}{#2}}{
15025 \backslash
15026 chunkref@i{#1}{#2}()}%
15027 \end_layout
15029 \begin_layout Plain Layout
15032 \end_layout
15034 \begin_layout Plain Layout
15037 \backslash
15039 \backslash
15040 chunkref@i#1#2(#3){%
15041 \end_layout
15043 \begin_layout Plain Layout
15045   
15046 \backslash
15048 \backslash
15049 zero{0}%
15050 \end_layout
15052 \begin_layout Plain Layout
15054   
15055 \backslash
15057 \backslash
15058 chunk{#2}%
15059 \end_layout
15061 \begin_layout Plain Layout
15063   
15064 \backslash
15066 \backslash
15067 chunkno{#1}%
15068 \end_layout
15070 \begin_layout Plain Layout
15072   
15073 \backslash
15075 \backslash
15076 chunkargs{#3}%
15077 \end_layout
15079 \begin_layout Plain Layout
15081   
15082 \backslash
15084 \backslash
15085 chunkno
15086 \backslash
15087 zero%
15088 \end_layout
15090 \begin_layout Plain Layout
15092     
15093 \backslash
15095 \backslash
15096 chunkname{#2-1}%
15097 \end_layout
15099 \begin_layout Plain Layout
15101   
15102 \backslash
15103 else%
15104 \end_layout
15106 \begin_layout Plain Layout
15108     
15109 \backslash
15111 \backslash
15112 chunkname{#2-
15113 \backslash
15114 chunkno}%
15115 \end_layout
15117 \begin_layout Plain Layout
15119   
15120 \backslash
15122 \end_layout
15124 \begin_layout Plain Layout
15126   
15127 \backslash
15129 \backslash
15130 lst@arg
15131 \backslash
15132 chunk%
15133 \end_layout
15135 \begin_layout Plain Layout
15137   
15138 \backslash
15139 lst@ReplaceIn
15140 \backslash
15141 chunk
15142 \backslash
15143 lst@filenamerpl%
15144 \end_layout
15146 \begin_layout Plain Layout
15148   
15149 \backslash
15150 LA{%
15151 \backslash
15152 moddef{%
15153 \end_layout
15155 \begin_layout Plain Layout
15157     {
15158 \backslash
15159 chunk}%
15160 \end_layout
15162 \begin_layout Plain Layout
15164     {%
15165 \end_layout
15167 \begin_layout Plain Layout
15169       
15170 \backslash
15171 nwtagstyle{}
15172 \backslash
15174 \end_layout
15176 \begin_layout Plain Layout
15178       
15179 \backslash
15181 \backslash
15182 chunkno
15183 \backslash
15184 zero%
15185 \end_layout
15187 \begin_layout Plain Layout
15189       
15190 \backslash
15191 else%
15192 \end_layout
15194 \begin_layout Plain Layout
15196       [
15197 \backslash
15198 chunkno]%
15199 \end_layout
15201 \begin_layout Plain Layout
15203       
15204 \backslash
15206 \end_layout
15208 \begin_layout Plain Layout
15210       
15211 \backslash
15213 \backslash
15214 chunkargs
15215 \backslash
15216 empty%
15217 \end_layout
15219 \begin_layout Plain Layout
15221       
15222 \backslash
15223 else%
15224 \end_layout
15226 \begin_layout Plain Layout
15228         (
15229 \backslash
15230 chunkref@args #3,)%
15231 \end_layout
15233 \begin_layout Plain Layout
15235       
15236 \backslash
15238 \end_layout
15240 \begin_layout Plain Layout
15242       ~
15243 \backslash
15244 subpageref{
15245 \backslash
15246 chunkname}%
15247 \end_layout
15249 \begin_layout Plain Layout
15251     }%
15252 \end_layout
15254 \begin_layout Plain Layout
15256   }%
15257 \end_layout
15259 \begin_layout Plain Layout
15261   
15262 \backslash
15264 \backslash
15265 endmoddef%
15266 \end_layout
15268 \begin_layout Plain Layout
15271 \end_layout
15273 \end_inset
15276 \end_layout
15278 \begin_layout Subsection
15279 The end
15280 \end_layout
15282 \begin_layout Standard
15283 \begin_inset listings
15284 inline false
15285 status open
15287 \begin_layout Plain Layout
15290 \end_layout
15292 \begin_layout Plain Layout
15295 \backslash
15296 makeatother
15297 \end_layout
15299 \end_inset
15302 \end_layout
15304 \begin_layout Chapter
15305 Extracting newfangle
15306 \end_layout
15308 \begin_layout Section
15309 Extracting from Lyx
15310 \end_layout
15312 \begin_layout Standard
15313 To extract from LyX, you will need to configure LyX as explained in section
15315 \begin_inset CommandInset ref
15316 LatexCommand ref
15317 reference "sub:Configuring-the-build"
15319 \end_inset
15322 \end_layout
15324 \begin_layout Standard
15325 \begin_inset CommandInset label
15326 LatexCommand label
15327 name "lyx-build-script"
15329 \end_inset
15331 And this lyx-build scrap will extract newfangle for me.
15332 \end_layout
15334 \begin_layout Chunk
15335 lyx-build,language=sh
15336 \end_layout
15338 \begin_layout Standard
15339 \begin_inset listings
15340 inline false
15341 status open
15343 \begin_layout Plain Layout
15345 #! /bin/sh
15346 \end_layout
15348 \begin_layout Plain Layout
15350 set -x
15351 \end_layout
15353 \begin_layout Plain Layout
15355 \end_layout
15357 \begin_layout Plain Layout
15360 \backslash
15361 chunkref{lyx-build-helper}>
15362 \end_layout
15364 \begin_layout Plain Layout
15366 cd $PROJECT_DIR || exit 1
15367 \end_layout
15369 \begin_layout Plain Layout
15371 \end_layout
15373 \begin_layout Plain Layout
15375 /usr/local/bin/newfangle -R./newfangle $TEX_SRC > ./newfangle
15376 \end_layout
15378 \begin_layout Plain Layout
15380 /usr/local/bin/newfangle -R./newfangle.module $TEX_SRC > ./newfangle.module
15381 \end_layout
15383 \begin_layout Plain Layout
15385 \end_layout
15387 \begin_layout Plain Layout
15390 \backslash
15391 chunkref{test:helpers}>
15392 \end_layout
15394 \begin_layout Plain Layout
15396 # run tests
15397 \end_layout
15399 \begin_layout Plain Layout
15401 ./newfangle -Rpca-test.awk $TEX_SRC | awk -f - || exit 1
15402 \end_layout
15404 \begin_layout Plain Layout
15407 \backslash
15408 chunkref{test:cromulence}>
15409 \end_layout
15411 \begin_layout Plain Layout
15414 \backslash
15415 chunkref{test:escapes}>
15416 \end_layout
15418 \end_inset
15421 \end_layout
15423 \begin_layout Standard
15424 With a lyx-build-helper
15425 \end_layout
15427 \begin_layout Chunk
15428 lyx-build-helper,language=sh
15429 \end_layout
15431 \begin_layout Standard
15432 \begin_inset listings
15433 inline false
15434 status open
15436 \begin_layout Plain Layout
15438 PROJECT_DIR="$LYX_r"
15439 \end_layout
15441 \begin_layout Plain Layout
15443 LYX_SRC="$PROJECT_DIR/${LYX_i%.tex}.lyx"
15444 \end_layout
15446 \begin_layout Plain Layout
15448 TEX_DIR="$LYX_p"
15449 \end_layout
15451 \begin_layout Plain Layout
15453 TEX_SRC="$TEX_DIR/$LYX_i"
15454 \end_layout
15456 \end_inset
15459 \end_layout
15461 \begin_layout Section
15462 Extracting from the command line
15463 \end_layout
15465 \begin_layout Standard
15466 First you will need the tex output, then you can extract:
15467 \end_layout
15469 \begin_layout Chunk
15470 lyx-build-manual,language=sh
15471 \end_layout
15473 \begin_layout Standard
15474 \begin_inset listings
15475 inline false
15476 status open
15478 \begin_layout Plain Layout
15480 lyx -e latex newfangle.lyx
15481 \end_layout
15483 \begin_layout Plain Layout
15485 newfangle -R./newfangle newfangle.tex > ./newfangle
15486 \end_layout
15488 \begin_layout Plain Layout
15490 newfangle -R./newfangle.module newfangle.tex > ./newfangle.module
15491 \end_layout
15493 \end_inset
15496 \end_layout
15498 \begin_layout Section
15499 Testing
15500 \end_layout
15502 \begin_layout Chunk
15503 test:helpers
15504 \end_layout
15506 \begin_layout Standard
15507 \begin_inset listings
15508 inline false
15509 status open
15511 \begin_layout Plain Layout
15513 passtest() {
15514 \end_layout
15516 \begin_layout Plain Layout
15518   if "$@"
15519 \end_layout
15521 \begin_layout Plain Layout
15523   then echo "Passed"
15524 \end_layout
15526 \begin_layout Plain Layout
15528   else echo "Failed"
15529 \end_layout
15531 \begin_layout Plain Layout
15533        return 1
15534 \end_layout
15536 \begin_layout Plain Layout
15538   fi
15539 \end_layout
15541 \begin_layout Plain Layout
15544 \end_layout
15546 \begin_layout Plain Layout
15548 \end_layout
15550 \begin_layout Plain Layout
15552 failtest() {
15553 \end_layout
15555 \begin_layout Plain Layout
15557   if ! "$@"
15558 \end_layout
15560 \begin_layout Plain Layout
15562   then echo "Passed"
15563 \end_layout
15565 \begin_layout Plain Layout
15567   else echo "Failed"
15568 \end_layout
15570 \begin_layout Plain Layout
15572        return 1
15573 \end_layout
15575 \begin_layout Plain Layout
15577   fi
15578 \end_layout
15580 \begin_layout Plain Layout
15583 \end_layout
15585 \end_inset
15588 \end_layout
15590 \begin_layout Part
15591 Tests
15592 \end_layout
15594 \begin_layout Chapter
15595 Chunk Parameters
15596 \end_layout
15598 \begin_layout Chunk
15599 tests-sub,language=,params=THING;colour
15600 \end_layout
15602 \begin_layout Standard
15603 \begin_inset listings
15604 inline false
15605 status open
15607 \begin_layout Plain Layout
15609 I see a ${THING} of 
15610 \end_layout
15612 \begin_layout Plain Layout
15614 colour ${colour}, 
15615 \end_layout
15617 \begin_layout Plain Layout
15619 looking closer =<
15620 \backslash
15621 chunkref{tests-sub-sub}(${colour})>
15622 \end_layout
15624 \end_inset
15627 \end_layout
15629 \begin_layout Chunk
15630 tests-sub-sub,params=colour
15631 \end_layout
15633 \begin_layout Standard
15634 \begin_inset listings
15635 inline false
15636 status open
15638 \begin_layout Plain Layout
15640 a funny shade of ${colour}
15641 \end_layout
15643 \end_inset
15646 \end_layout
15648 \begin_layout Chunk
15649 tests
15650 \end_layout
15652 \begin_layout Standard
15653 \begin_inset listings
15654 inline false
15655 status open
15657 \begin_layout Plain Layout
15659 What do you see? "=<
15660 \backslash
15661 chunkref{tests-sub}(joe, red)>"
15662 \end_layout
15664 \begin_layout Plain Layout
15666 Well, fancy!
15667 \end_layout
15669 \end_inset
15672 \end_layout
15674 \begin_layout Standard
15675 Should generate output:
15676 \end_layout
15678 \begin_layout Chunk
15679 tests-result
15680 \end_layout
15682 \begin_layout Standard
15683 \begin_inset listings
15684 inline false
15685 status open
15687 \begin_layout Plain Layout
15689 What do you see? "I see a joe of 
15690 \end_layout
15692 \begin_layout Plain Layout
15694                   colour red, 
15695 \end_layout
15697 \begin_layout Plain Layout
15699                   looking closer a funny shade of red"
15700 \end_layout
15702 \begin_layout Plain Layout
15704 Well, fancy!
15705 \end_layout
15707 \begin_layout Plain Layout
15709 \end_layout
15711 \end_inset
15714 \end_layout
15716 \end_body
15717 \end_document