1 #LyX 1.6.4 created this file. For more info see http://www.lyx.org/
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,
15 \use_default_options true
24 \font_typewriter default
25 \font_default_family default
32 \paperfontsize default
35 \pdf_title "Newfangle"
36 \pdf_author "Sam Liddicott"
37 \pdf_subject "Literate Programing"
38 \pdf_keywords "notangle noweb noweave literate programming cweb"
40 \pdf_bookmarksnumbered false
41 \pdf_bookmarksopen false
42 \pdf_bookmarksopenlevel 1
54 \paperorientation portrait
57 \paragraph_separation skip
59 \quotes_language english
62 \paperpagestyle default
63 \tracking_changes false
83 \begin_layout Chapter*
87 \begin_layout Standard
92 is a tool for newfangled literate programming.
93 Newfangled is defined as
95 New and often needlessly novel
104 \begin_layout Standard
105 In this case, newfangled means yet another new and improved method for literate
109 \begin_layout Standard
114 has a long history starting with the great
118 himself, whose literate programming tools seem to make use of as many escape
119 sequences for semantic markup as TeX itself.
122 \begin_layout Standard
131 set of tools (notangle, noweave and noroots) and helpfully reduced the
132 amount of magic character sequences to pretty much just
133 \begin_inset Flex CharStyle:Code
136 \begin_layout Plain Layout
143 \begin_inset Flex CharStyle:Code
146 \begin_layout Plain Layout
152 , and in doing so brought the wonders of literate programming within my
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.
162 \begin_layout Standard
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
173 \begin_layout Standard
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
184 \begin_layout Standard
185 Significantly, newfangle is just one program which replaces various programs
187 Noweave is done away with and implemented directly as LaTeX macros, and
188 noroots is implemented as a function of the untangler
195 \begin_layout Standard
196 Newfangle is written in awk for portability reasons, awk being available
198 A python conversion will probably be attempted for the benefit of LyX.
199 (Hasn't anyone implemented awk in python yet?)
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.
208 \begin_layout Section*
212 \begin_layout Enumerate
213 ^^ is always going to be a problem, see texbytopic 1.2.2 (Work out what I
217 \begin_layout Enumerate
218 copy over up to date Makefile guide from noweb-lyx document
221 \begin_layout Enumerate
222 Make chunk-name settings only apply to chunks with that name
225 \begin_layout Enumerate
226 indent of multi-line chunks may be mode dependant (i.e.
227 not in string literals)
230 \begin_layout Enumerate
231 add support for other commands in =<...>, starting with
233 label which takes the line-number within the chunk, and maybe should also
234 take the chunk name/page
237 \begin_layout Enumerate
238 cant have listing inside a ruled box
241 \begin_layout Enumerate
242 when a parameterized chunk is included as well as the #line emission, say
243 what the paremeters were for that invocation.
246 \begin_layout Enumerate
249 chunkref[3]{preamble} to include a certain chunk needs to work in newfangle.awk
250 instead of failing to be recognized at all
253 \begin_layout Enumerate
254 make in-listins labels track the chunk ref too, and make
256 chunref{[2],thing}> resolve to 41c (or d, or whatever chunk the 2nd chunk
260 \begin_layout Enumerate
263 chunkref in text needs a trailing space maybe, it keeps butting up to the
267 \begin_layout Enumerate
268 because the white-space indent is output by the parent chunk, the #line
269 is that of the parent chunk.
270 White space indents must be passed to the child chunk
273 \begin_layout Chapter*
277 \begin_layout Standard
278 \begin_inset CommandInset label
284 Newfangle is licensed under the GPL 3
285 \begin_inset CommandInset citation
292 This doesn't mean that you can't use or distribute newfangle with sources
293 of an incompatible license, but it means you must make the source of newfangle
298 gpl3-copyright,language=
301 \begin_layout Standard
302 \begin_inset listings
306 \begin_layout Plain Layout
308 newfangle - fully featured notangle replacement in awk
311 \begin_layout Plain Layout
315 \begin_layout Plain Layout
317 Copyright (C) Sam Liddicott 2009
320 \begin_layout Plain Layout
324 \begin_layout Plain Layout
326 This program is free software: you can redistribute it and/or modify
329 \begin_layout Plain Layout
331 it under the terms of the GNU General Public License as published by
334 \begin_layout Plain Layout
336 the Free Software Foundation, either version 3 of the License, or
339 \begin_layout Plain Layout
341 (at your option) any later version.
344 \begin_layout Plain Layout
348 \begin_layout Plain Layout
350 This program is distributed in the hope that it will be useful,
353 \begin_layout Plain Layout
355 but WITHOUT ANY WARRANTY; without even the implied warranty of
358 \begin_layout Plain Layout
360 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
364 \begin_layout Plain Layout
366 GNU General Public License for more details.
369 \begin_layout Plain Layout
373 \begin_layout Plain Layout
375 You should have received a copy of the GNU General Public License
378 \begin_layout Plain Layout
380 along with this program.
381 If not, see <http://www.gnu.org/licenses/>.
384 \begin_layout Plain Layout
393 \begin_layout Standard
394 \begin_inset CommandInset toc
395 LatexCommand tableofcontents
406 \begin_layout Chapter
410 \begin_layout Standard
411 Newfangle is a replacement for noweb, which consists of
412 \begin_inset Flex CharStyle:Code
415 \begin_layout Plain Layout
422 \begin_inset Flex CharStyle:Code
425 \begin_layout Plain Layout
432 \begin_inset Flex CharStyle:Code
435 \begin_layout Plain Layout
444 \begin_layout Standard
446 \begin_inset Flex CharStyle:Code
449 \begin_layout Plain Layout
456 \begin_inset Flex CharStyle:Code
459 \begin_layout Plain Layout
465 it can read multiple named files, or from stdin.
468 \begin_layout Section
472 \begin_layout Standard
473 The -r option causes newfangle to behave like noroots.
476 \begin_layout LyX-Code
477 newfangle -r filename.tex
480 \begin_layout Standard
481 will print out the newfangle roots of a tex file.
485 \begin_layout Standard
487 \begin_inset Flex CharStyle:Code
490 \begin_layout Plain Layout
496 command, the roots are not enclosed in
497 \begin_inset Flex CharStyle:Code
500 \begin_layout Plain Layout
506 , unless at least one of the roots is defined using the
507 \begin_inset Flex CharStyle:Code
510 \begin_layout Plain Layout
517 \begin_inset Flex CharStyle:Code
520 \begin_layout Plain Layout
529 \begin_layout Standard
530 Also, unlike noroots, it prints out all roots --- not just those that are
532 I find that a root not being used, doesn't make it particularly top level.
533 My convention is that top level roots to be extracted begin with
534 \begin_inset Flex CharStyle:Code
537 \begin_layout Plain Layout
543 and have the form of a filename.
546 \begin_layout Section
550 \begin_layout Standard
552 \begin_inset Flex CharStyle:Code
555 \begin_layout Plain Layout
562 \begin_inset Flex CharStyle:Code
565 \begin_layout Plain Layout
571 options are supported.
574 \begin_layout Standard
575 The standard way to extract a file would be:
578 \begin_layout LyX-Code
579 newfangle -R./Makefile.inc newfangle.tex > ./Makefile.inc
582 \begin_layout Standard
584 \begin_inset Flex CharStyle:Code
587 \begin_layout Plain Layout
594 \begin_inset Flex CharStyle:Code
597 \begin_layout Plain Layout
603 option does not break indenting; also the
604 \begin_inset Flex CharStyle:Code
607 \begin_layout Plain Layout
613 option does not interrupt (and break) multi-line C macros --- or indeed
614 any line ending with a backslash.
615 This does mean that sometimes the compiler might calculate the source line
616 wrongly when generating error messages in such cases, but there isn't any
617 other way around if multi-line macros include other chunks.
620 \begin_layout Section
621 Formatting source in LaTeX
624 \begin_layout Standard
625 The noweave replacement is a set of LaTeX macros dependant upon
629 , and which can be included with:
632 \begin_layout LyX-Code
635 usepackage{newfangle.sty}
638 \begin_layout Standard
639 The LaTeX macros are shown in section
640 \begin_inset CommandInset ref
642 reference "sec:Latex-Macros"
646 , and are part of a LyX module file
647 \begin_inset Flex CharStyle:Code
650 \begin_layout Plain Layout
656 , which automatically includes the macros in the document pre-amble when
657 the newfangle LyX module is used.
660 \begin_layout Standard
661 Because the noweave replacement is impemented in LaTeX, there is no processing
662 stage required before running the
663 \begin_inset Flex CharStyle:Code
666 \begin_layout Plain Layout
673 LaTeX may need running two or more times, so that the code chunk references
674 can be fully calculated.
677 \begin_layout Standard
679 \begin_inset Flex CharStyle:Code
682 \begin_layout Plain Layout
688 package is required as it is used for formatting the code chunk captions
691 \begin_layout Standard
693 \begin_inset Flex CharStyle:Code
696 \begin_layout Plain Layout
702 package is also required, as it is used for formatting the code chunks
706 \begin_layout Standard
708 \begin_inset Flex CharStyle:Code
711 \begin_layout Plain Layout
717 package is also required.
720 \begin_layout Chapter
721 Literate Programming with Newfangle
724 \begin_layout Standard
726 Should really follow on from a part-0 explanation of what literate programming
730 \begin_layout Chapter
731 Using Newfangle with LyX
734 \begin_layout Section
738 \begin_layout Subsection
739 Installing the LyX module
742 \begin_layout Standard
744 \begin_inset Flex CharStyle:Code
747 \begin_layout Plain Layout
753 to your LyX layouts directory, which for unix users will be
754 \begin_inset Flex CharStyle:Code
757 \begin_layout Plain Layout
766 \begin_layout Standard
767 You will need to reconfigure LyX by clicking Tools\SpecialChar \menuseparator
768 Reconfigure, and then
772 \begin_layout Subsection
773 \begin_inset CommandInset label
775 name "sub:Configuring-the-build"
779 Configuring the build script
782 \begin_layout Standard
783 Make sure you don't have a conversion defined for Lyx → Program
786 \begin_layout Standard
787 From the menu Tools\SpecialChar \menuseparator
788 Preferences, add a conversion from Latex(Plain) → Program
792 \begin_layout LyX-Code
793 set -x ; newfangle -Rlyx-build $$i |
796 \begin_layout LyX-Code
797 env LYX_b=$$b LYX_i=$$i LYX_o=$$o LYX_p=$$p LYX_r=$$r bash
800 \begin_layout Standard
801 (But don't cut-n-paste it from this document or you'll be pasting a multi-line
802 string which will break your lyx preferences file).
806 \begin_layout Standard
807 I hope that one day, LyX will set these into the environment when calling
811 \begin_layout Standard
812 You may also want to consider adding options to this conversion\SpecialChar \ldots{}
816 \begin_layout LyX-Code
817 parselog=/usr/share/lyx/scripts/listerrors
820 \begin_layout Standard
821 \SpecialChar \ldots{}
822 but if you do you will lose your stderr
826 \begin_layout Plain Layout
827 There is some bash plumbing to get a copy of stderr but this footnote is
836 \begin_layout Standard
837 Now, a shell script chunk called
838 \begin_inset Flex CharStyle:Code
841 \begin_layout Plain Layout
847 will be extracted and run whenever you choose the Document\SpecialChar \menuseparator
852 \begin_layout Standard
853 The lyx-build script for this document is in section
854 \begin_inset CommandInset ref
856 reference "lyx-build-script"
860 and on a unix system will extract
861 \begin_inset Flex CharStyle:Code
864 \begin_layout Plain Layout
871 \begin_inset Flex CharStyle:Code
874 \begin_layout Plain Layout
883 \begin_layout Subsection
884 Preparing your Lyx document
887 \begin_layout Standard
888 It is not necessary to base your literate document on any of the original
889 LyX literate classes; so select a regular class for your document type.
892 \begin_layout Standard
908 \begin_layout Standard
909 In the drop-down style listbox you should notice a new style defined, called
917 \begin_layout Standard
918 When you wish to insert a literate chunk, you enter it's plain name in the
919 Chunk style, instead of the older method that used
920 \begin_inset Flex CharStyle:Code
923 \begin_layout Plain Layout
930 Following the chunk name, you insert a listing with: Insert\SpecialChar \menuseparator
934 \begin_layout Standard
935 Inside the white listing box you can type (or paste using shift+ctrl+V)
937 There is not need to use ctrl+enter at the end of lines as with some older
938 LyX literate techniques --- just press enter as normal.
941 \begin_layout Subsubsection
942 Customising the listing appearance
945 \begin_layout Standard
946 In the final document, the code is formatted using the
951 The chunk style doesn't just define the chunk name, but can also define
952 any other chunk options supported by the lstlistings package
953 \begin_inset Flex CharStyle:Code
956 \begin_layout Plain Layout
965 In fact, what you type in the chunk style is raw latex.
966 If you want to set the chunk language without having to right-click the
968 \begin_inset Flex CharStyle:Code
971 \begin_layout Plain Layout
977 after the chunk name.
980 \begin_layout Standard
981 Of course you can do this by editing the listings box advanced properties
982 by right-clicking on the listings box, but that takes longer, and you can't
983 see at-a-glance what the advanced settings are while editing the document;
984 also advanced settings apply only to that box --- the chunk settings apply
985 through the rest of the document
989 \begin_layout Plain Layout
990 It ought to apply only to subsequent chunks of the same name.
997 \begin_inset Note Note
1000 \begin_layout Plain Layout
1001 So make sure they only apply to chunks of that name
1009 \begin_layout Subsubsection
1010 Global customisations
1013 \begin_layout Standard
1018 is used to set the code chunks, it's
1019 \begin_inset Flex CharStyle:Code
1022 \begin_layout Plain Layout
1030 command can be used in the pre-amble to set some document wide settings.
1033 \begin_layout Standard
1034 If your source has many words with long sequences of capital letters, then
1036 \begin_inset Flex CharStyle:Code
1039 \begin_layout Plain Layout
1040 columns=fullflexible
1045 may be a good idea, or the capital letters will get crowded.
1046 (I think lstlistings ought to use a slightly smaller font for captial letters
1047 so that they still fit).
1050 \begin_layout Standard
1052 \begin_inset Flex CharStyle:Code
1055 \begin_layout Plain Layout
1063 looks more normal for code, but has no bold (unless luximono is used, but
1064 it doesn't work for me); so I use
1065 \begin_inset Flex CharStyle:Code
1068 \begin_layout Plain Layout
1078 \begin_inset Flex CharStyle:Code
1081 \begin_layout Plain Layout
1090 \begin_inset Flex CharStyle:Code
1093 \begin_layout Plain Layout
1094 columns=fullflexible
1099 is used or the wrong letter spacing is used.
1102 \begin_layout Standard
1103 In my LeTeX pre-amble I usually specialise my code format with:
1107 document-preamble,language=tex
1110 \begin_layout Standard
1111 \begin_inset listings
1115 \begin_layout Plain Layout
1122 \begin_layout Plain Layout
1126 definecolor{darkgreen}{rgb}{0,0.5,0}
1129 \begin_layout Plain Layout
1133 lstset{numbers=left, stepnumber=5, numbersep=5pt, breaklines=false,
1136 \begin_layout Plain Layout
1145 \begin_layout Plain Layout
1152 \begin_layout Plain Layout
1156 tiny,language=C,columns=fullflexible,
1159 \begin_layout Plain Layout
1161 numberfirstline=true
1164 \begin_layout Plain Layout
1174 \begin_layout Chapter
1175 Newfangle with Makefiles
1178 \begin_layout Standard
1179 \begin_inset Note Note
1182 \begin_layout Plain Layout
1183 This chapter needs revising
1189 \begin_inset Note Greyedout
1192 \begin_layout Plain Layout
1193 This chapter needs revising
1198 Here we describe a Makefile.inc that you can include in your own Makefiles,
1199 or glue as a recursive make to other projects.
1202 \begin_layout Standard
1203 The Makefile.inc described here was put together for a Samba4 vfs module,
1204 but can be used in any Make project, including automake projects.
1207 \begin_layout Section
1208 A word about makefiles formats
1211 \begin_layout Standard
1212 Whitespace formatting is very important in a Makefile.
1213 The first character of each command line must be a TAB.
1216 \begin_layout LyX-Code
1217 target: pre-requisite
1218 \begin_inset Newline newline
1222 \begin_inset Newline newline
1228 \begin_layout Standard
1229 But a TAB is pretty hard to enter into most of the Lyx formats and insets
1231 An alternative is to use a semi-colon after the pre-requisite, and a backslash
1232 at the end of each line (except the last).
1233 Then any whitespace (or none) can prefix each action.
1236 \begin_layout LyX-Code
1237 target: pre-requisite ;
1240 \begin_inset Newline newline
1246 \begin_inset Newline newline
1252 \begin_layout Standard
1253 This is the style that we use and it works pretty well for GNU make at least.
1256 \begin_layout Standard
1257 We also adopt a convention that code chunks whose names beginning with ./
1258 should always be automatically extracted from the document.
1259 Code chunks whose names do not begin with ./ are for internal reference.
1260 (This doesn't prevent such chunks from being extracted directly).
1263 \begin_layout Section
1264 Boot-strapping the extraction
1267 \begin_layout Subsection
1271 \begin_layout Standard
1272 \begin_inset CommandInset label
1274 name "sub:Bootstrap-Using-a-Makefile"
1278 It seems convenient to have the makefile extract or update the C source
1279 files as part of it's operation.
1280 It also seems convenient to have the makefile itself extracted from this
1284 \begin_layout Standard
1285 It would also be convenient to have the code to extract the makefile from
1286 this document to also be part of this document, however we have to start
1287 somewhere and this unfortunately requires us to type at least a few words
1288 by hand to start things off.
1291 \begin_layout Standard
1292 Therefore we will have a minimal root fragment, which, when extracted, can
1293 cope with extracting the rest of the source.
1294 perhaps with this shell script, which could be called
1299 \begin_inset Note Note
1302 \begin_layout Plain Layout
1303 FIX THIS CHUNK AND TEST IT
1315 \begin_layout Standard
1316 \begin_inset listings
1320 \begin_layout Plain Layout
1325 \begin_layout Plain Layout
1329 \begin_layout Plain Layout
1331 MAKE_SRC="${1:-${NW_LYX:-../../noweb-lyx/noweb-lyx3.lyx}}"
1334 \begin_layout Plain Layout
1336 MAKE_SRC=`dirname "$MAKE_SRC"`/`basename "$MAKE_SRC" .lyx`
1339 \begin_layout Plain Layout
1341 NOWEB_SRC="${2:-${NOWEB_SRC:-$MAKE_SRC.lyx}}"
1344 \begin_layout Plain Layout
1346 lyx -e latex $MAKE_SRC
1349 \begin_layout Plain Layout
1353 \begin_layout Plain Layout
1355 newfangle -R./Makefile.inc ${MAKE_SRC}.tex
1360 \begin_layout Plain Layout
1362 | sed "/NEWFANGLE_SOURCE=/s/^/#/;T;aNOWEB_SOURCE=$NEWFANGLE_SRC"
1367 \begin_layout Plain Layout
1369 | cpif ./Makefile.inc
1372 \begin_layout Plain Layout
1376 \begin_layout Plain Layout
1378 make -f ./Makefile.inc newfangle_sources
1386 \begin_layout Standard
1387 The general Makefile can be invoked with
1391 and can also be included into any automake file to automatically re-generate
1395 \begin_layout Standard
1400 can be extracted with this command:
1403 \begin_layout LyX-Code
1404 lyx -e latex newfangle.lyx &&
1409 \begin_layout LyX-Code
1410 newfangle newfangle.lyx > ./autoboot
1413 \begin_layout Standard
1414 This looks simple enough, but as mentioned, newfangle has to be had from
1415 somewhere before it can be extracted.
1418 \begin_layout Subsection
1419 \begin_inset Note Note
1422 \begin_layout Plain Layout
1423 MERGE THIS WITH THE SECTIONS OF THIS DOCUMENT
1428 \SpecialChar \ldots{}
1432 \begin_layout Standard
1433 When the lyx-build chunk is executed, the current directory will be a temporary
1435 \begin_inset Flex CharStyle:Code
1438 \begin_layout Plain Layout
1444 will refer to the tex file in this temporary directory.
1445 This is unfortunate as our makefile wants to run from the project directory
1446 where the Lyx file is kept.
1449 \begin_layout Standard
1450 We can extract the project directory from $$r, and derive the probable Lyx
1451 filename from the noweb file that Lyx generated.
1458 \begin_layout Standard
1459 \begin_inset listings
1463 \begin_layout Plain Layout
1465 PROJECT_DIR="$LYX_r"
1468 \begin_layout Plain Layout
1470 LYX_SRC="$PROJECT_DIR/${LYX_i%.tex}.lyx"
1473 \begin_layout Plain Layout
1478 \begin_layout Plain Layout
1480 TEX_SRC="$TEX_DIR/$LYX_i"
1488 \begin_layout Standard
1489 And then we can define a lyx-build fragment similar to the autoboot fragment
1496 \begin_layout Standard
1497 \begin_inset listings
1501 \begin_layout Plain Layout
1506 \begin_layout Plain Layout
1510 chunkref{lyx-build-helper}>
1513 \begin_layout Plain Layout
1515 cd $PROJECT_DIR || exit 1
1518 \begin_layout Plain Layout
1522 \begin_layout Plain Layout
1524 #/usr/bin/newfangle -filter ./notanglefix-filter
1529 \begin_layout Plain Layout
1531 # -R./Makefile.inc "../../noweb-lyx/noweb-lyx3.lyx"
1536 \begin_layout Plain Layout
1538 # | sed '/NOWEB_SOURCE=/s/=.*/=samba4-dfs.lyx/'
1543 \begin_layout Plain Layout
1548 \begin_layout Plain Layout
1553 \begin_layout Plain Layout
1555 #make -f ./Makefile.inc newfangle_sources
1563 \begin_layout Section
1567 \begin_layout Subsection
1568 Including Makefile.inc
1571 \begin_layout Standard
1572 \begin_inset CommandInset label
1574 name "sub:Keeping-extracted-files"
1578 Makefile.inc will cope with extracting all the other source files from this
1579 document and keeping them up to date.
1583 \begin_layout Standard
1584 It may also be included by a Makefile or Makefile.am defined in a Lyx document
1585 to automatically deal with the extraction of source files and documents.
1588 \begin_layout Standard
1589 A makefile has two parts; variables must be defined before the targets that
1597 \begin_layout Standard
1598 \begin_inset listings
1602 \begin_layout Plain Layout
1606 chunkref{Makefile.inc-vars}>
1609 \begin_layout Plain Layout
1613 chunkref{Makefile.inc-targets}>
1621 \begin_layout Standard
1623 \begin_inset Flex CharStyle:Code
1626 \begin_layout Plain Layout
1632 to hold the name of this Lyx file.
1639 \begin_layout Standard
1640 \begin_inset listings
1644 \begin_layout Plain Layout
1649 \begin_layout Plain Layout
1651 LITERATE_SOURCE=$(LYX_SOURCE)
1659 \begin_layout Subsection
1660 Recursive use of Makefile.inc
1663 \begin_layout Standard
1664 The makefile glue described here is used when building Samba4 vfs modules.
1667 \begin_layout Standard
1668 If you are defining a module of an existing program you may find it easier
1669 to use a slight recursive make instead of including the makefile directly.
1670 This way there is less chance of definitions in Makefile.inc interfering
1671 with definitions in the main makefile, or with definitions in other Makefile.inc
1672 from other noweb modules.
1675 \begin_layout Standard
1676 The glue works by adding a .PHONY target to call the recursive make, and
1677 adding this target as an additional pre-requisite to the existing targets.
1680 \begin_layout Standard
1681 In this example, the existing build system already has a build target for
1683 \begin_inset Flex CharStyle:Code
1686 \begin_layout Plain Layout
1692 , so we just add another pre-requisite to that.
1694 \begin_inset Flex CharStyle:Code
1697 \begin_layout Plain Layout
1703 as a pre-requisite, the stamp file's modified time indicating when all
1704 sources were extracted.
1711 \begin_layout Standard
1712 \begin_inset listings
1716 \begin_layout Plain Layout
1718 $(example_srcdir)/example.o: $(example_srcdir)/example.tex.stamp
1726 \begin_layout Standard
1727 The target for this new pre-requisite is generated by a recursive make using
1728 Makefile.inc which will make sure that the source is up to date, before
1729 it is built by the main projects makefile.
1736 \begin_layout Standard
1737 \begin_inset listings
1741 \begin_layout Plain Layout
1743 $(example_srcdir)/example.tex.stamp: $(example_srcdir)/example.tex ;
1748 \begin_layout Plain Layout
1750 cd $(example_srcdir) &&
1755 \begin_layout Plain Layout
1757 $(MAKE) -f Makefile.inc newfangle_sources
1765 \begin_layout Standard
1766 We can do similar glue for the docs, clean and distclean targets.
1767 In this example our build system is using a double colon for these targets,
1768 so we use the same in our glue.
1775 \begin_layout Standard
1776 \begin_inset listings
1780 \begin_layout Plain Layout
1785 \begin_layout Plain Layout
1787 .PHONY: docs_example
1790 \begin_layout Plain Layout
1792 docs_example:: ; cd $(example_srcdir) &&
1797 \begin_layout Plain Layout
1799 $(MAKE) -f Makefile.inc docs
1802 \begin_layout Plain Layout
1806 \begin_layout Plain Layout
1808 clean:: clean_example
1811 \begin_layout Plain Layout
1813 .PHONEY: clean_example
1816 \begin_layout Plain Layout
1818 clean_example: ; cd $(example_srcdir) &&
1823 \begin_layout Plain Layout
1825 $(MAKE) -f Makefile.inc clean
1828 \begin_layout Plain Layout
1832 \begin_layout Plain Layout
1834 distclean:: distclean_example
1837 \begin_layout Plain Layout
1839 .PHONY: distclean_example
1842 \begin_layout Plain Layout
1844 distclean_example: ; cd $(example_srcdir) &&
1849 \begin_layout Plain Layout
1851 $(MAKE) -f Makefile.inc distclean
1859 \begin_layout Standard
1860 We could do similarly for install targets to install the generated docs.
1863 \begin_layout Subsection
1864 \begin_inset CommandInset label
1866 name "sub:Converting-from-Lyx"
1870 Converting from Lyx to LaTeX
1873 \begin_layout Standard
1874 The first stage will always be to convert the Lyx file to a LaTeX file;
1875 this must be so not only because newfangle needs to to run on a TeX file,
1876 but also because the Lyx command
1878 server-goto-file-line
1882 \begin_layout Plain Layout
1885 server-goto-file-line
1887 is used to position the Lyx cursor at the compiler errors.
1894 insists that the line number provided is a line in the TeX file, and always
1895 reverse maps this to derive the line in the Lyx docment.
1896 \begin_inset Note Note
1899 \begin_layout Plain Layout
1900 The tex file should probably be an automake extra dist sources or something,
1901 so that it gets produced and packaged by make dist
1909 \begin_layout Standard
1910 The command [[lyx -e literate noweb-lyx.lyx]] will produce [[noweb-lyx.nw]]
1911 a tex file, so we define the noweb target to be the same as the Lyx file
1912 but with the .nw extension.
1919 \begin_layout Standard
1920 \begin_inset listings
1924 \begin_layout Plain Layout
1926 TEX_SOURCE=$(LYX_SOURCE:.lyx=.tex)
1935 Makefile.inc-targets
1938 \begin_layout Standard
1939 \begin_inset listings
1943 \begin_layout Plain Layout
1945 $(TEX_SOURCE): $(LYX_SOURCE) ;
1950 \begin_layout Plain Layout
1955 \begin_layout Plain Layout
1957 clean_tex: ; rm -f -- $(TEX_SOURCE)
1965 \begin_layout Subsection
1966 Extracting Program Source
1969 \begin_layout Standard
1970 The program source is extracted using newfangle, which is designed to operate
1971 on a LaTeX document.
1979 \begin_layout Standard
1980 \begin_inset listings
1984 \begin_layout Plain Layout
1986 NEWFANGLE_SOURCE=$(TEX_SOURCE)
1994 \begin_layout Standard
1995 The Lyx document can result in any number of source documents, but not all
1996 of these will be changed each time the Lyx document is updated.
1997 We certainly don't want to update the timestamps of these files and cause
1998 the whole source tree to be recompiled just because the Lyx document was
2003 \begin_layout Standard
2004 To solve this problem we use a stamp file which is always updated each time
2005 the sources are extracted from the LaTeX document.
2006 If the stamp file is older than the LaTeX document, then we can make an
2007 attempt to re-extract the sources.
2014 \begin_layout Standard
2015 \begin_inset listings
2019 \begin_layout Plain Layout
2021 NEWFANGLE_SOURCE_STAMP=$(NEWFANGLE_SOURCE).stamp
2030 Makefile.inc-targets
2033 \begin_layout Standard
2034 \begin_inset listings
2038 \begin_layout Plain Layout
2040 $(NEWFANGLE_SOURCE_STAMP): $(NEWFANGLE_SOURCE)
2045 \begin_layout Plain Layout
2047 $(NEWFANGLE_SOURCES) ;
2052 \begin_layout Plain Layout
2054 echo > $(NEWFANGLE_SOURCE_STAMP)
2057 \begin_layout Plain Layout
2059 clean_stamp: ; rm -f $(NEWFANGLE_SOURCE_STAMP)
2062 \begin_layout Plain Layout
2072 \begin_layout Subsection
2073 Extracting C sources
2076 \begin_layout Standard
2078 \begin_inset Flex CharStyle:Code
2081 \begin_layout Plain Layout
2087 to hold the names of all the C source files defined in this document.
2088 We compute this only once, by means of := in assignent.
2089 The sed deletes the any <
2090 \begin_inset space \hspace*{}
2095 \begin_inset space \hspace*{}
2099 > which may surround the roots names (for noroots compatibility).
2103 \begin_layout Standard
2104 As we use chunk names beginning with ./ to denote top level fragments that
2105 should be extracted, we filter out all fragments that do not begin with
2113 \begin_layout Standard
2114 \begin_inset listings
2118 \begin_layout Plain Layout
2127 \begin_layout Plain Layout
2129 NEWFANGLE_SOURCES:=$(shell
2134 \begin_layout Plain Layout
2136 newfangle -r $(NEWFANGLE_SOURCE) |
2141 \begin_layout Plain Layout
2143 sed -e 's/^[<][<]//;s/[>][>]$$//;/^$(NEWFANGLE_PREFIX)/!d'
2148 \begin_layout Plain Layout
2150 -e 's/^$(NEWFANGLE_PREFIX)/
2157 \begin_layout Plain Layout
2168 Makefile.inc-targets
2171 \begin_layout Standard
2172 \begin_inset listings
2176 \begin_layout Plain Layout
2178 .PHONY: echo_newfangle_sources
2181 \begin_layout Plain Layout
2183 echo_newfangle_sources: ; @echo $(NEWFANGLE_SOURCES)
2191 \begin_layout Standard
2192 We define a convenient target called
2193 \begin_inset Flex CharStyle:Code
2196 \begin_layout Plain Layout
2202 to re-extract the source if the LaTeX file has been updated.
2206 Makefile.inc-targets
2209 \begin_layout Standard
2210 \begin_inset listings
2214 \begin_layout Plain Layout
2216 .PHONY: newfangle_sources
2219 \begin_layout Plain Layout
2221 newfangle_sources: $(NEWFANGLE_SOURCE_STAMP)
2229 \begin_layout Standard
2230 And also a convenient target to remove extracted sources.
2234 Makefile.inc-targets
2237 \begin_layout Standard
2238 \begin_inset listings
2242 \begin_layout Plain Layout
2244 .PHONY: clean_newfangle_sources
2247 \begin_layout Plain Layout
2249 clean_newfangle_sources: ;
2254 \begin_layout Plain Layout
2256 rm -f -- $(NEWFANGLE_SOURCE_STAMP) $(NEWFANGLE_SOURCES)
2264 \begin_layout Standard
2266 \begin_inset Flex CharStyle:Code
2269 \begin_layout Plain Layout
2275 macro takes 4 arguments: the filename (1), some extensions to match (2)
2276 and a some shell command to return if the filename matches the exentions
2284 \begin_layout Standard
2285 \begin_inset listings
2289 \begin_layout Plain Layout
2291 if_extension=$(if $(findstring $(suffix $(1)),$(2)),$(3),$(4))
2299 \begin_layout Standard
2300 For some source files like C files, we want to output the line number and
2301 filename of the original LaTeX document from which the source came.
2304 \begin_layout Standard
2305 To make this easier we define the file extensions for which we want to do
2313 \begin_layout Standard
2314 \begin_inset listings
2318 \begin_layout Plain Layout
2328 \begin_layout Standard
2329 We can then use the if_extensions macro to define a macro which expands
2331 \begin_inset Flex CharStyle:Code
2334 \begin_layout Plain Layout
2340 option if newfangle is being invoked in a C source file, so that C compile
2341 errors will refer to the line number in the Lyx document.
2349 \begin_layout Standard
2350 \begin_inset listings
2354 \begin_layout Plain Layout
2359 \begin_layout Plain Layout
2361 nf_line=-L -T$(TABS)
2364 \begin_layout Plain Layout
2371 \begin_layout Plain Layout
2373 $(call if_extension,$(2),$(C_EXTENSIONS),$(nf_line))
2378 \begin_layout Plain Layout
2388 \begin_layout Standard
2389 We can use a similar trick to define an
2393 macro which takes just the filename as an argument and can return a pipeline
2394 stage calling the indent command.
2395 Indent can be turned off with
2396 \begin_inset Flex CharStyle:Code
2399 \begin_layout Plain Layout
2400 make newfangle_sources indent=
2412 \begin_layout Standard
2413 \begin_inset listings
2417 \begin_layout Plain Layout
2419 indent_options=-npro -kr -i8 -ts8 -sob -l80 -ss -ncs
2422 \begin_layout Plain Layout
2424 indent=$(call if_extension,$(1),$(C_EXTENSIONS),
2429 \begin_layout Plain Layout
2431 | indent $(indent_options))
2439 \begin_layout Standard
2440 We now define the pattern for extracting a file.
2441 The files are written using noweb's
2447 \begin_layout Plain Layout
2450 So you still need noweb installed in order to use cpif
2456 \begin_inset Note Note
2459 \begin_layout Plain Layout
2462 Write an awk version
2469 so that the file timestamp will not be touched if the contents haven't
2471 This avoids the need to rebuild the entire project because of a typographical
2472 change in the documentation, or if only a few C source files have changed.
2479 \begin_layout Standard
2480 \begin_inset listings
2484 \begin_layout Plain Layout
2486 newfangle_extract=@mkdir -p $(dir $(1)) &&
2491 \begin_layout Plain Layout
2493 $(call newfangle,$(2),$(1)) > "$(1).tmp" &&
2498 \begin_layout Plain Layout
2500 cat "$(1).tmp" $(indent) | cpif "$(1)"
2505 \begin_layout Plain Layout
2507 && rm -- "$(1).tmp" ||
2512 \begin_layout Plain Layout
2514 (echo error newfangling $(1) from $(2) ; exit 1)
2522 \begin_layout Standard
2523 We define a target which will extract or update all sources.
2524 To do this we first defined a makefile template that can do this for any
2525 source file in the LaTeX document.
2532 \begin_layout Standard
2533 \begin_inset listings
2537 \begin_layout Plain Layout
2539 define NEWFANGLE_template
2542 \begin_layout Plain Layout
2549 \begin_layout Plain Layout
2551 $$(call newfangle_extract,$(1),$(2))
2554 \begin_layout Plain Layout
2556 NEWFANGLE_TARGETS+=$(1)
2559 \begin_layout Plain Layout
2569 \begin_layout Standard
2570 We then enumerate the discovered
2571 \begin_inset Flex CharStyle:Code
2574 \begin_layout Plain Layout
2580 to generate a makefile rule for each one using the makefile template we
2585 Makefile.inc-targets
2588 \begin_layout Standard
2589 \begin_inset listings
2593 \begin_layout Plain Layout
2595 $(foreach source,$(NEWFANGLE_SOURCES),
2600 \begin_layout Plain Layout
2602 $(eval $(call NEWFANGLE_template,$(source),$(NEWFANGLE_SOURCE)))
2607 \begin_layout Plain Layout
2617 \begin_layout Standard
2618 These will all be built with NEWFANGLE_SOURCE_STAMP.
2621 \begin_layout Standard
2622 We also remove the generated sources on a
2630 Makefile.inc-targets
2633 \begin_layout Standard
2634 \begin_inset listings
2638 \begin_layout Plain Layout
2640 _distclean: clean_newfangle_sources
2648 \begin_layout Subsection
2649 Extracting Documentation
2652 \begin_layout Standard
2653 We then identify the intermediate stages of the documentation and their
2654 build and clean targets.
2657 \begin_layout Subsubsection
2661 \begin_layout Standard
2662 We produce a pdf file from the tex file.
2669 \begin_layout Standard
2670 \begin_inset listings
2674 \begin_layout Plain Layout
2676 NEWFANGLE_PDF=$(TEX_SOURCE:.tex=.pdf)
2684 \begin_layout Standard
2685 We run pdflatex twice to be sure that the contents and aux files are up
2687 We certainly are required to run pdflatex twice if these files do not exist!
2691 Makefile.inc-targets
2694 \begin_layout Standard
2695 \begin_inset listings
2699 \begin_layout Plain Layout
2701 $(NEWFANGLE_PDF): $(TEX_SOURCE); pdflatex $< && pdflatex $<
2704 \begin_layout Plain Layout
2706 clean_pdf: ; rm -f -- $(NEWFANGLE_PDF)
2711 \begin_layout Plain Layout
2713 $(TEX_SOURCE:.tex=.toc)
2718 \begin_layout Plain Layout
2720 $(TEX_SOURCE:.tex=.log)
2725 \begin_layout Plain Layout
2727 $(TEX_SOURCE:.tex=.aux)
2735 \begin_layout Subsubsection
2739 \begin_layout Standard
2740 Currently we only build pdf as a final format, but NEWFANGLE_DOCS may later
2741 hold other output formats.
2748 \begin_layout Standard
2749 \begin_inset listings
2753 \begin_layout Plain Layout
2755 NEWFANGLE_DOCS=$(NEWFANGLE_PDF)
2763 \begin_layout Standard
2764 We also define newfangle_docs as a convenient phony target<
2768 Makefile.inc-targets
2771 \begin_layout Standard
2772 \begin_inset listings
2776 \begin_layout Plain Layout
2778 .PHONY: newfangle_docs
2781 \begin_layout Plain Layout
2783 newfangle_docs: $(NEWFANGLE_DOCS)
2786 \begin_layout Plain Layout
2788 docs: newfangle_docs
2796 \begin_layout Standard
2797 And define a convenient clean_noweb_docs which we add to the regular clean
2802 Makefile.inc-targets
2805 \begin_layout Standard
2806 \begin_inset listings
2810 \begin_layout Plain Layout
2812 .PHONEY: clean_newfangle_docs
2815 \begin_layout Plain Layout
2817 clean_newfangle_docs: clean_tex clean_pdf
2820 \begin_layout Plain Layout
2822 clean: clean_newfangle_docs
2825 \begin_layout Plain Layout
2829 \begin_layout Plain Layout
2831 distclean_newfangle_docs: clean_tex clean_newfangle_docs
2834 \begin_layout Plain Layout
2836 distclean: clean distclean_newfangle_docs
2844 \begin_layout Subsection
2848 \begin_layout Standard
2849 If Makefile.inc is included into Makefile, then extracted files can be updated
2853 \begin_layout LyX-Code
2854 make newfangle_sources
2857 \begin_layout Standard
2861 \begin_layout LyX-Code
2862 make -f Makefile.inc newfangle_sources
2869 \begin_layout Chapter
2870 Newfangle awk source code
2873 \begin_layout Standard
2874 We use the copyright notice from chapter
2875 \begin_inset CommandInset ref
2877 reference "cha:License"
2885 ./newfangle,language=awk,morestring=[b]{/},morekeywords=else
2888 \begin_layout Standard
2889 \begin_inset listings
2893 \begin_layout Plain Layout
2898 \begin_layout Plain Layout
2902 chunkref{gpl3-copyright}>
2905 \begin_layout Plain Layout
2914 \begin_layout Standard
2915 We also use code from Arnold Robbins public domain getopt (1993 revision)
2917 \begin_inset CommandInset ref
2919 reference "cha:getopt"
2923 , and naturally want to attribute this appropriately.
2926 \begin_layout Standard
2927 \begin_inset listings
2931 \begin_layout Plain Layout
2935 \begin_layout Plain Layout
2937 # NOTE: Arnold Robbins public domain getopt for awk is also used:
2940 \begin_layout Plain Layout
2944 chunkref{getopt.awk-header}>
2947 \begin_layout Plain Layout
2951 \begin_layout Plain Layout
2955 chunkref{getopt.awk-getopt()}>
2958 \begin_layout Plain Layout
2967 \begin_layout Standard
2968 And include the following chunks
2975 \begin_layout Standard
2976 \begin_inset listings
2980 \begin_layout Plain Layout
2984 chunkref{helper-functions}>
2987 \begin_layout Plain Layout
2991 chunkref{mode-tracker}>
2994 \begin_layout Plain Layout
2998 chunkref{parse_chunk_args}>
3001 \begin_layout Plain Layout
3005 chunkref{chunk-storage-functions}>
3008 \begin_layout Plain Layout
3012 chunkref{output_chunk_names()}>
3015 \begin_layout Plain Layout
3019 chunkref{output_chunks()}>
3022 \begin_layout Plain Layout
3026 chunkref{write_chunk()}>
3029 \begin_layout Plain Layout
3033 chunkref{expand_chunk_args()}>
3036 \begin_layout Plain Layout
3043 \begin_layout Plain Layout
3047 chunkref{recognize-chunk}>
3050 \begin_layout Plain Layout
3062 \begin_layout Section
3066 \begin_layout Standard
3067 The portable way to erase an array in awk is to split the empty string,
3072 awk-delete-array,params=ARRAY
3075 \begin_layout Standard
3076 \begin_inset listings
3080 \begin_layout Plain Layout
3082 split("", ${ARRAY});
3091 dump-array,params=ARRAY
3094 \begin_layout Standard
3095 \begin_inset listings
3099 \begin_layout Plain Layout
3110 \begin_layout Plain Layout
3112 for (_x in ${ARRAY}) {
3115 \begin_layout Plain Layout
3117 print _x "=" ${ARRAY}[_x] "
3122 \begin_layout Plain Layout
3127 \begin_layout Plain Layout
3143 \begin_layout Section
3147 \begin_layout Standard
3148 Fatal errors are issued with the error function:
3152 error(),append=helper-functions
3155 \begin_layout Standard
3156 \begin_inset listings
3160 \begin_layout Plain Layout
3162 function error(message)
3165 \begin_layout Plain Layout
3170 \begin_layout Plain Layout
3172 print "ERROR: " FILENAME ":" FNR " " message > "/dev/stderr";
3175 \begin_layout Plain Layout
3180 \begin_layout Plain Layout
3190 \begin_layout Standard
3191 \begin_inset listings
3195 \begin_layout Plain Layout
3197 function warning(message)
3200 \begin_layout Plain Layout
3205 \begin_layout Plain Layout
3207 print "WARNING: " FILENAME ":" FNR " " message > "/dev/stderr";
3210 \begin_layout Plain Layout
3215 \begin_layout Plain Layout
3225 \begin_layout Chapter
3229 \begin_layout Standard
3230 LaTeX arguments to lstlistings macros are a comma seperated list of key-value
3232 Values containing commas are enclosed in
3233 \begin_inset Flex CharStyle:Code
3236 \begin_layout Plain Layout
3243 \begin_inset Flex CharStyle:Code
3246 \begin_layout Plain Layout
3252 , which is to be expected for LaTeX.
3255 \begin_layout Standard
3256 A sample expressions is:
3259 \begin_layout LyX-Code
3260 name=thomas, params={a, b}, something, something-else
3263 \begin_layout Standard
3264 but we see that this is just a simpler form of this expression:
3267 \begin_layout LyX-Code
3268 name=freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3271 \begin_layout Standard
3272 We may consider that we need a function that can parse such LaTeX expressions
3273 and assign the values to an
3277 associated array, perhaps using a recursive parser into a multi-dimensional
3282 \begin_layout Plain Layout
3283 as AWK doesn't have nested-hash support
3291 \begin_layout Standard
3292 \begin_inset Tabular
3293 <lyxtabular version="3" rows="6" columns="2">
3295 <column alignment="left" valignment="top" width="0">
3296 <column alignment="left" valignment="top" width="0">
3298 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3301 \begin_layout Plain Layout
3307 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3310 \begin_layout Plain Layout
3318 <cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
3321 \begin_layout Plain Layout
3327 <cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3330 \begin_layout Plain Layout
3338 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3341 \begin_layout Plain Layout
3347 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3350 \begin_layout Plain Layout
3358 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3361 \begin_layout Plain Layout
3367 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3370 \begin_layout Plain Layout
3378 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3381 \begin_layout Plain Layout
3387 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3390 \begin_layout Plain Layout
3398 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3401 \begin_layout Plain Layout
3407 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3410 \begin_layout Plain Layout
3424 \begin_layout Standard
3425 Oon reflection it seems that sometimes such nesting is not desirable, as
3426 the braces are also used to delimit values that contain commas --- we may
3430 \begin_layout LyX-Code
3431 name={williamson, freddie}
3434 \begin_layout Standard
3436 \begin_inset Flex CharStyle:Code
3439 \begin_layout Plain Layout
3446 \begin_inset Flex CharStyle:Code
3449 \begin_layout Plain Layout
3458 \begin_layout Standard
3459 In fact we are not so interested in the detail so as to be bothered by this,
3460 which turns out to be a good thing for two reasons.
3461 Firstly LaTeX has a malleable parser with no strict syntax, and secondly
3463 \begin_inset Flex CharStyle:Code
3466 \begin_layout Plain Layout
3473 \begin_inset Flex CharStyle:Code
3476 \begin_layout Plain Layout
3482 should count as two items will be context dependant anyway.
3485 \begin_layout Standard
3486 We need to parse this latex for only one reason; which is that we are extending
3487 lstlistings to add some additional arguments which will be used to express
3488 chunk parameters and other chunk options.
3491 \begin_layout Section
3492 Additional lstlstings parameters
3495 \begin_layout Standard
3496 Further on we define a
3497 \begin_inset Flex CharStyle:Code
3500 \begin_layout Plain Layout
3508 LaTeX macro whose arguments will consist of a the chunk name, optionally
3509 followed by a comma and then a comma separated list of arguments.
3510 In fact we will just need to prefix
3511 \begin_inset Flex CharStyle:Code
3514 \begin_layout Plain Layout
3520 to the arguments to in order to create valid lstlistings arguments.
3524 \begin_layout Standard
3525 There will be other arguments supported too;
3528 \begin_layout Description
3529 params As an extension to many literate-programming styles, newfangle permits
3530 code chunks to take parameters and thus operate somewhat like C pre-processor
3531 macros, or like C++ templates.
3532 Chunk parameters are declared with a chunk argument called
3533 \begin_inset Flex CharStyle:Code
3536 \begin_layout Plain Layout
3542 , which holds a semi-colon separated list of parameters, like this:
3545 \begin_layout LyX-Code
3546 achunk,language=C,params=name;address
3549 \begin_layout Description
3550 addto a named chunk that this chunk is to be included into.
3551 This saves the effort of having to declare another listing of the named
3552 chunk merely to include this one.
3555 \begin_layout Standard
3557 \begin_inset Flex Chunkref
3560 \begin_layout Plain Layout
3566 will accept two paramters,
3567 \begin_inset Flex CharStyle:Code
3570 \begin_layout Plain Layout
3576 being the text to parse, and
3577 \begin_inset Flex CharStyle:Code
3580 \begin_layout Plain Layout
3586 being an array to receive the parsed values as described above.
3587 The optional parameter
3588 \begin_inset Flex CharStyle:Code
3591 \begin_layout Plain Layout
3597 is used during recursion to build up the multi-dimensional array path.
3604 \begin_layout Standard
3605 \begin_inset listings
3609 \begin_layout Plain Layout
3613 chunkref{get_chunk_args()}>
3625 \begin_layout Standard
3626 \begin_inset listings
3630 \begin_layout Plain Layout
3632 function get_chunk_args(text, values,
3635 \begin_layout Plain Layout
3637 # optional parameters
3640 \begin_layout Plain Layout
3642 path, # hierarchical precursors
3645 \begin_layout Plain Layout
3650 \begin_layout Plain Layout
3660 \begin_layout Standard
3661 The strategy is to parse the name, and then look for a value.
3662 If the value begins with a brace
3663 \begin_inset Flex CharStyle:Code
3666 \begin_layout Plain Layout
3672 , then we recurse and consume as much of the text as necessary, returning
3673 the remaining text when we encounter a leading close-brace
3674 \begin_inset Flex CharStyle:Code
3677 \begin_layout Plain Layout
3684 This being the strategy --- and executed in a loop --- we realise that
3685 we must first look for the closing brace (perhaps preceded by white space)
3686 in order to terminate the recursion, and returning remaining text.
3689 \begin_layout Standard
3690 \begin_inset listings
3694 \begin_layout Plain Layout
3699 \begin_layout Plain Layout
3701 split("", next_chunk_args);
3704 \begin_layout Plain Layout
3706 while(length(text)) {
3709 \begin_layout Plain Layout
3711 if (match(text, "^ *}(.*)", a)) {
3714 \begin_layout Plain Layout
3719 \begin_layout Plain Layout
3724 \begin_layout Plain Layout
3728 chunkref{parse-chunk-args}>
3731 \begin_layout Plain Layout
3736 \begin_layout Plain Layout
3741 \begin_layout Plain Layout
3751 \begin_layout Standard
3752 \begin_inset Note Note
3755 \begin_layout Plain Layout
3756 Use BNF package here
3761 We can see that the text could be inspected with this regex:
3768 \begin_layout Standard
3769 \begin_inset listings
3773 \begin_layout Plain Layout
3775 if (! match(text, " *([^,=]*[^,= ]) *(([,=]) *(([^,}]*) *,* *(.*))|)$", a))
3779 \begin_layout Plain Layout
3784 \begin_layout Plain Layout
3794 \begin_layout Standard
3796 \begin_inset Flex CharStyle:Code
3799 \begin_layout Plain Layout
3805 will have the following values:
3808 \begin_layout Standard
3809 \begin_inset Tabular
3810 <lyxtabular version="3" rows="7" columns="2">
3812 <column alignment="center" valignment="top" width="0">
3813 <column alignment="left" valignment="top" width="0">
3815 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3818 \begin_layout Plain Layout
3824 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3827 \begin_layout Plain Layout
3835 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3838 \begin_layout Plain Layout
3844 <cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3847 \begin_layout Plain Layout
3855 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3858 \begin_layout Plain Layout
3864 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3867 \begin_layout Plain Layout
3868 =freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3875 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3878 \begin_layout Plain Layout
3884 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3887 \begin_layout Plain Layout
3895 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3898 \begin_layout Plain Layout
3904 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3907 \begin_layout Plain Layout
3908 freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3915 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3918 \begin_layout Plain Layout
3924 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3927 \begin_layout Plain Layout
3935 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3938 \begin_layout Plain Layout
3944 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3947 \begin_layout Plain Layout
3948 , foo={bar=baz, quux={quirk, a=fleeg}}, etc
3961 \begin_layout Standard
3963 \begin_inset Flex CharStyle:Code
3966 \begin_layout Plain Layout
3973 \begin_inset Flex CharStyle:Code
3976 \begin_layout Plain Layout
3982 and signify whether the option named in
3983 \begin_inset Flex CharStyle:Code
3986 \begin_layout Plain Layout
3992 has a value or not (respectively).
3995 \begin_layout Standard
3996 If the option does have a value, then if the expression
3997 \begin_inset Flex CharStyle:Code
4000 \begin_layout Plain Layout
4007 \begin_inset Flex CharStyle:Code
4010 \begin_layout Plain Layout
4016 it will signify that we need to recurse:
4019 \begin_layout Standard
4020 \begin_inset listings
4024 \begin_layout Plain Layout
4029 \begin_layout Plain Layout
4034 \begin_layout Plain Layout
4036 if (substr(a[4],1,1) == "{") {
4039 \begin_layout Plain Layout
4041 text = get_chunk_args(substr(a[4],2), values, path name SUBSEP);
4044 \begin_layout Plain Layout
4049 \begin_layout Plain Layout
4051 values[path name]=a[5];
4054 \begin_layout Plain Layout
4059 \begin_layout Plain Layout
4064 \begin_layout Plain Layout
4069 \begin_layout Plain Layout
4071 values[path name]="";
4074 \begin_layout Plain Layout
4079 \begin_layout Plain Layout
4089 \begin_layout Standard
4090 We can test this function like this:
4097 \begin_layout Standard
4098 \begin_inset listings
4102 \begin_layout Plain Layout
4106 chunkref{get_chunk_args()}>
4109 \begin_layout Plain Layout
4114 \begin_layout Plain Layout
4119 \begin_layout Plain Layout
4123 \begin_layout Plain Layout
4125 print get_chunk_args("name=freddie, foo={bar=baz, quux={quirk, a=fleeg}},
4129 \begin_layout Plain Layout
4134 \begin_layout Plain Layout
4136 print "a[" b "] => " a[b];
4139 \begin_layout Plain Layout
4144 \begin_layout Plain Layout
4154 \begin_layout Standard
4155 which should give this output:
4159 gca-test.awk-results
4162 \begin_layout Standard
4163 \begin_inset listings
4167 \begin_layout Plain Layout
4169 a[foo.quux.quirk] =>
4172 \begin_layout Plain Layout
4174 a[foo.quux.a] => fleeg
4177 \begin_layout Plain Layout
4182 \begin_layout Plain Layout
4187 \begin_layout Plain Layout
4197 \begin_layout Section
4198 Parsing chunk arguments
4201 \begin_layout Standard
4202 \begin_inset CommandInset label
4204 name "cha:Chunk Arguments"
4211 \begin_layout Standard
4212 Arguments to paramterized chunks are expressed in round brackets as a comma
4213 separated list of optional arguments.
4214 For example, a chunk that is defined with:
4217 \begin_layout LyX-Code
4220 Chunk{achunk, params=name ; address}
4223 \begin_layout Standard
4224 could be invoked as:
4227 \begin_layout LyX-Code
4230 chunkref{achunk}(John Jones, jones@example.com)
4233 \begin_layout Standard
4234 An argument list may be as simple as in
4235 \begin_inset Flex CharStyle:Code
4238 \begin_layout Plain Layout
4241 chunkref{pull}(thing, otherthing)
4249 \begin_layout LyX-Code
4252 chunkref{pull}(things[x, y], get_other_things(a, "(all)"))
4255 \begin_layout Standard
4256 --- which for all it's commas and quotes and parenthesis represents only
4258 \begin_inset Flex CharStyle:Code
4261 \begin_layout Plain Layout
4268 \begin_inset Flex CharStyle:Code
4271 \begin_layout Plain Layout
4272 get_other_things(a, "(all)")
4280 \begin_layout Standard
4281 If we simply split parameter list on commas, then the comma in
4282 \begin_inset Flex CharStyle:Code
4285 \begin_layout Plain Layout
4291 would split into two seperate arguments:
4292 \begin_inset Flex CharStyle:Code
4295 \begin_layout Plain Layout
4302 \begin_inset Flex CharStyle:Code
4305 \begin_layout Plain Layout
4311 --- neither of which make sense on their own.
4314 \begin_layout Standard
4315 One way to prevent this would be by refusing to split text between matching
4317 \begin_inset Flex CharStyle:Code
4320 \begin_layout Plain Layout
4327 \begin_inset Flex CharStyle:Code
4330 \begin_layout Plain Layout
4337 \begin_inset Flex CharStyle:Code
4340 \begin_layout Plain Layout
4347 \begin_inset Flex CharStyle:Code
4350 \begin_layout Plain Layout
4357 \begin_inset Flex CharStyle:Code
4360 \begin_layout Plain Layout
4367 \begin_inset Flex CharStyle:Code
4370 \begin_layout Plain Layout
4376 and most likely also
4377 \begin_inset Flex CharStyle:Code
4380 \begin_layout Plain Layout
4387 \begin_inset Flex CharStyle:Code
4390 \begin_layout Plain Layout
4397 \begin_inset Flex CharStyle:Code
4400 \begin_layout Plain Layout
4407 \begin_inset Flex CharStyle:Code
4410 \begin_layout Plain Layout
4417 Of course this also makes it impossible to pass such mis-matched code fragments
4418 as parameters, but I think that it would be hard for readers to cope with
4419 authors who would pass such code unbalanced fragments as chunk parameters
4423 \begin_layout Plain Layout
4424 I know that I couldn't cope with users doing such things, and although the
4425 GPL3 license prevents me from actually forbidding anyone from trying, if
4426 they want it to work they'll have to write the code themselves and not
4427 expect any support from me.
4435 \begin_layout Standard
4436 Unfortunately, the full set of matching delimiters may vary from language
4438 In certain C++ template contexts,
4439 \begin_inset Flex CharStyle:Code
4442 \begin_layout Plain Layout
4449 \begin_inset Flex CharStyle:Code
4452 \begin_layout Plain Layout
4458 would count as delimiters, and yet in other contexts they would not.
4461 \begin_layout Standard
4462 This puts me in the unfortunate position of having to parse-somewhat all
4463 programming languages without knowing what they are!
4466 \begin_layout Standard
4467 However, if this universal mode-tracking is possible, then parsing the arguments
4469 Such a mode tracker is described in chapter
4470 \begin_inset CommandInset ref
4472 reference "cha:modes"
4476 and used here with simplicity.
4483 \begin_layout Standard
4484 \begin_inset listings
4488 \begin_layout Plain Layout
4490 function parse_chunk_args(language, text, values, mode,
4493 \begin_layout Plain Layout
4498 \begin_layout Plain Layout
4503 \begin_layout Plain Layout
4508 \begin_layout Plain Layout
4512 chunkref{new-mode-tracker}(context, language, mode)>
4515 \begin_layout Plain Layout
4517 rest = mode_tracker(context, text, values);
4520 \begin_layout Plain Layout
4525 \begin_layout Plain Layout
4527 for(c=1; c <= context[0, "values"]; c++) {
4530 \begin_layout Plain Layout
4532 values[c] = context[0, "values", c];
4535 \begin_layout Plain Layout
4540 \begin_layout Plain Layout
4545 \begin_layout Plain Layout
4555 \begin_layout Section
4556 Expanding parameters in the text
4559 \begin_layout Standard
4560 Within the body of the chunk, the parameters are referred to with:
4561 \begin_inset Flex CharStyle:Code
4564 \begin_layout Plain Layout
4571 \begin_inset Flex CharStyle:Code
4574 \begin_layout Plain Layout
4581 There is a strong case that a LaTeX style notation should be used, like
4584 param{name} which would be expressed in the listing as =<
4586 param{name}> and be rendered as
4587 \begin_inset listings
4591 \begin_layout Plain Layout
4601 Such notation would make me go blind, but I do intend to adopt it
4605 \begin_layout Plain Layout
4606 Probably when LyX's listings inset can recognize and render it, so that
4607 I no longer have to type =<\SpecialChar \ldots{}
4616 \begin_layout Standard
4617 We therefore need a function
4618 \begin_inset Flex CharStyle:Code
4621 \begin_layout Plain Layout
4627 which will take a block of text, a list of permitted parameters, and the
4628 arguments which must substitute for the parameters.
4632 \begin_layout Standard
4633 \begin_inset CommandInset label
4635 name "Here-we-split"
4639 Here we split the text on
4640 \begin_inset Flex CharStyle:Code
4643 \begin_layout Plain Layout
4649 which means that all parts except the first will begin with a parameter
4650 name which will be terminated by
4651 \begin_inset Flex CharStyle:Code
4654 \begin_layout Plain Layout
4661 The split function will consume the literal
4662 \begin_inset Flex CharStyle:Code
4665 \begin_layout Plain Layout
4678 \begin_layout Standard
4679 \begin_inset listings
4683 \begin_layout Plain Layout
4685 function expand_chunk_args(text, params, args,
4688 \begin_layout Plain Layout
4690 p, text_array, next_text, v, t, l)
4693 \begin_layout Plain Layout
4698 \begin_layout Plain Layout
4700 if (split(text, text_array, "
4707 \begin_layout Plain Layout
4711 chunkref{substitute-chunk-args}>
4714 \begin_layout Plain Layout
4719 \begin_layout Plain Layout
4723 \begin_layout Plain Layout
4728 \begin_layout Plain Layout
4738 \begin_layout Standard
4739 First, we produce an associative array of substitution values indexed by
4741 This will serve as a cache, allowing us to look up the replacement values
4742 as we extract each name.
4746 substitute-chunk-args
4749 \begin_layout Standard
4750 \begin_inset listings
4754 \begin_layout Plain Layout
4759 \begin_layout Plain Layout
4761 v[params[p]]=args[p];
4764 \begin_layout Plain Layout
4774 \begin_layout Standard
4775 We accumulate substituted text in the variable
4776 \begin_inset Flex CharStyle:Code
4779 \begin_layout Plain Layout
4786 As the first part of the split function is the part before the delimiter
4788 \begin_inset Flex CharStyle:Code
4791 \begin_layout Plain Layout
4797 in our case --- this part will never contain a parameter reference, so
4798 we assign this directly to the result kept in
4799 \begin_inset Flex CharStyle:Code
4802 \begin_layout Plain Layout
4809 \begin_inset listings
4813 \begin_layout Plain Layout
4823 \begin_layout Standard
4824 We then iterate over the remaining values in the array
4828 \begin_layout Plain Layout
4829 I don't know why I think that it will enumerate the array in order, but
4836 \begin_inset Note Note
4839 \begin_layout Plain Layout
4840 So fix it or porve it
4845 , and substitute each reference for it's argument.
4848 \begin_layout Standard
4849 \begin_inset listings
4853 \begin_layout Plain Layout
4855 for(t=2; t in text_array; t++) {
4858 \begin_layout Plain Layout
4862 chunkref{substitute-chunk-arg}>
4865 \begin_layout Plain Layout
4875 \begin_layout Standard
4877 \begin_inset Flex CharStyle:Code
4880 \begin_layout Plain Layout
4886 a valid parameter reference will consist of valid parameter name terminated
4888 \begin_inset Flex CharStyle:Code
4891 \begin_layout Plain Layout
4898 A valid character name begins with the underscore or a letter, and may
4899 contain letters, digits or underscores.
4902 \begin_layout Standard
4903 A valid looking reference that is not actually the name of a parameter will
4904 be and not substituted.
4905 This is good because there is nothing to substitute anyway, and it avoids
4906 clashes when writing code for languages where ${\SpecialChar \ldots{}
4907 } is a valid construct
4908 --- such constructs will not be interfered with unless the parameter name
4913 substitute-chunk-arg
4916 \begin_layout Standard
4917 \begin_inset listings
4921 \begin_layout Plain Layout
4923 if (match(text_array[t], "^([a-zA-Z_][a-zA-Z0-9_]*)}", l) &&
4926 \begin_layout Plain Layout
4931 \begin_layout Plain Layout
4936 \begin_layout Plain Layout
4938 text = text v[l[1]] substr(text_array[t], length(l[1])+2);
4941 \begin_layout Plain Layout
4946 \begin_layout Plain Layout
4948 text = text "${" text_array[t];
4951 \begin_layout Plain Layout
4961 \begin_layout Chapter
4965 \begin_layout Standard
4966 \begin_inset CommandInset label
4975 \begin_layout Section
4979 \begin_layout Standard
4980 lstlistings and newfangle both recognize source languages, and perform some
4982 lstlistings can detect strings and comments within a language definition
4983 and perform suitable rendering, such as italics for comments, and visible-space
4987 \begin_layout Standard
4988 Newfangle similarly can recognize strings, and comments, etc, within a language,
4989 so that any chunks included with
4990 \begin_inset Flex CharStyle:Code
4993 \begin_layout Plain Layout
5001 can be suitably escape or quoted.
5004 \begin_layout Subsection
5005 Modes to keep code together
5008 \begin_layout Standard
5009 As an example, in the C language there are a few parse modes, affecting
5010 the interpretation of characters.
5013 \begin_layout Standard
5014 One parse mode is the strings mode.
5015 The string mode is commenced by an un-escaped quotation mark
5016 \begin_inset Flex CharStyle:Code
5019 \begin_layout Plain Layout
5025 and terminated by the same.
5026 Within the string mode, only one additional mode can be commenced, it is
5028 \begin_inset Flex CharStyle:Code
5031 \begin_layout Plain Layout
5039 , which is always terminated by the folloing character.
5042 \begin_layout Standard
5044 \begin_inset Flex CharStyle:Code
5047 \begin_layout Plain Layout
5053 which is terminated by a
5054 \begin_inset Flex CharStyle:Code
5057 \begin_layout Plain Layout
5063 (unless it occurs in a string).
5066 \begin_layout Standard
5067 Consider this line of C code:
5070 \begin_layout Standard
5071 \begin_inset Formula $\mathtt{things\underbrace{[\mathtt{x,\ y}]}_{1.\ [\ mode},\ get\_other\_things\underbrace{(\mathtt{a,\overbrace{"\mathtt{(all)}"}})}_{2.\ (\ mode}^{3.\ "\ mode}}$
5077 \begin_layout Standard
5078 Mode nesting prevents the close parenthesis in quote mode (part 3) from
5079 terminating the parenthesis mode (part 2).
5082 \begin_layout Standard
5083 Each language has a set of modes, the default mode being the null mode.
5084 Each mode can lead to other modes.
5087 \begin_layout Subsection
5088 Modes to included chunks
5091 \begin_layout Standard
5092 For instance, consider this chunk with
5093 \begin_inset Flex CharStyle:Code
5096 \begin_layout Plain Layout
5106 example-perl,language=perl
5109 \begin_layout Standard
5110 \begin_inset listings
5114 \begin_layout Plain Layout
5124 \begin_layout Standard
5125 If it were included in a chunk with
5126 \begin_inset Flex CharStyle:Code
5129 \begin_layout Plain Layout
5139 example-sh,language=sh
5142 \begin_layout Standard
5143 \begin_inset listings
5147 \begin_layout Plain Layout
5151 chunkref{example-perl}>"
5159 \begin_layout Standard
5160 newfangle would need to generate output like this if it were to work:
5163 \begin_layout LyX-Code
5171 \begin_layout Standard
5172 See that the double quote
5173 \begin_inset Flex CharStyle:Code
5176 \begin_layout Plain Layout
5183 \begin_inset Flex CharStyle:Code
5186 \begin_layout Plain Layout
5192 in the regex have been quoted with a back-slash to protect them from shell
5196 \begin_layout Standard
5197 If that were then included in a chunk with
5198 \begin_inset Flex CharStyle:Code
5201 \begin_layout Plain Layout
5211 example-makefile,language=make
5214 \begin_layout Standard
5215 \begin_inset listings
5219 \begin_layout Plain Layout
5224 \begin_layout Plain Layout
5228 chunkref{example-sh}>
5236 \begin_layout Standard
5237 We would need the output to look like this --- note the $$:
5240 \begin_layout LyX-Code
5244 \begin_layout LyX-Code
5252 \begin_layout Standard
5253 In order to make this work, we need to define a mode-tracker supporting
5254 each language, that can detect the various quoting modes, and provide a
5255 transformation that must be applied to any included text so that included
5256 text will be interpreted correctly after any interpolation that it may
5257 be subject to at run-time.
5260 \begin_layout Standard
5261 For example, the sed transformation for text to be inserted into sh double-quote
5262 d strings would be something like:
5265 \begin_layout LyX-Code
5289 \begin_layout Standard
5291 \begin_inset Flex CharStyle:Code
5294 \begin_layout Plain Layout
5305 \begin_layout Standard
5306 \begin_inset Note Note
5309 \begin_layout Plain Layout
5310 I don't think this example is true
5315 The mode tracker must also track nested mode-changes, as in this
5316 \begin_inset Flex CharStyle:Code
5319 \begin_layout Plain Layout
5328 \begin_layout LyX-Code
5329 echo "hello `id \SpecialChar \ldots{}
5333 \begin_layout LyX-Code
5337 \begin_layout Plain Layout
5343 hphantom{echo "hello `id}
5351 \begin_layout Standard
5352 Any characters inserted at the point marked ↑ would need to be escaped,
5354 \begin_inset Flex CharStyle:Code
5357 \begin_layout Plain Layout
5364 First it would need escaping for the back-ticks `, and then for the double-quot
5368 \begin_layout Standard
5369 Escaping need not occur if the format and mode of the included chunk matches
5370 that of the including chunk.
5373 \begin_layout Standard
5374 As each chunk is output a new mode tracker for that language is initialized
5375 in it's normal state.
5376 As text is output for that chunk the output mode is tracked.
5377 When a new chunk is included, a transformation appropriate to that mode
5378 is selected and pushed onto a stack of transformations.
5379 Any text to be output is first passed through this stack of transformations.
5382 \begin_layout Standard
5383 It remains to consider if the chunk-include function should return it's
5384 generated text so that the caller can apply any transformations (and formatting
5385 ), or if it should apply the stack of transformations itself.
5388 \begin_layout Standard
5389 Note that the transformed text should have the property of not being able
5390 to change the mode in the current chunk.
5393 \begin_layout Standard
5394 \begin_inset Note Note
5397 \begin_layout Plain Layout
5398 Note chunk parameters should probably also be transformed
5406 \begin_layout Section
5407 Language Mode Definitions
5410 \begin_layout Standard
5411 All modes are stored in a single multi-dimensional hash.
5412 The first index is the language, and the second index is the mode-identifier.
5413 The third indexes are terminators, and optionally, submodes, and delimiters.
5416 \begin_layout Standard
5417 A useful set of mode definitions for a nameless general C-type language
5419 (Don't be confused by the double backslash escaping needed in awk.
5420 One set of escaping is for the string, and the second set of escaping is
5423 \begin_inset Note Note
5426 \begin_layout Plain Layout
5429 mode{}> command which will allow us to signify that a string is regex and
5430 thus newfangle will quote it for us.
5438 \begin_layout Standard
5439 Submodes are entered by the characters
5440 \begin_inset Flex CharStyle:Code
5443 \begin_layout Plain Layout
5452 \begin_inset Flex CharStyle:Code
5455 \begin_layout Plain Layout
5462 \begin_inset Flex CharStyle:Code
5465 \begin_layout Plain Layout
5472 \begin_inset Flex CharStyle:Code
5475 \begin_layout Plain Layout
5482 \begin_inset Flex CharStyle:Code
5485 \begin_layout Plain Layout
5492 \begin_inset Flex CharStyle:Code
5495 \begin_layout Plain Layout
5502 \begin_inset Flex CharStyle:Code
5505 \begin_layout Plain Layout
5515 common-mode-definitions,params=language
5518 \begin_layout Standard
5519 \begin_inset listings
5523 \begin_layout Plain Layout
5525 modes[${language}, "", "submodes" ]="
5551 \begin_layout Standard
5552 In the default mode, a comma surrounded by un-important white space is a
5553 delimiter of language items.
5556 \begin_layout Standard
5557 \begin_inset listings
5561 \begin_layout Plain Layout
5563 modes[${language}, "", "delimiters"]=" *, *";
5571 \begin_layout Standard
5572 and should pass this test:
5575 \begin_layout Standard
5576 \begin_inset Note Note
5579 \begin_layout Plain Layout
5580 Why do the tests run in
5581 \begin_inset Quotes eld
5585 \begin_inset Quotes erd
5589 \begin_inset Quotes eld
5593 \begin_inset Quotes erd
5605 test:mode-definitions
5608 \begin_layout Standard
5609 \begin_inset listings
5613 \begin_layout Plain Layout
5615 parse_chunk_args("c-like", "1,2,3", a, "");
5618 \begin_layout Plain Layout
5620 if (a[1] != "1") e++;
5623 \begin_layout Plain Layout
5625 if (a[2] != "2") e++;
5628 \begin_layout Plain Layout
5630 if (a[3] != "3") e++;
5633 \begin_layout Plain Layout
5635 if (length(a) != 3) e++;
5638 \begin_layout Plain Layout
5642 chunkref{pca-test.awk:summary}>
5645 \begin_layout Plain Layout
5649 \begin_layout Plain Layout
5651 parse_chunk_args("c-like", "joe, red", a, "");
5654 \begin_layout Plain Layout
5656 if (a[1] != "joe") e++;
5659 \begin_layout Plain Layout
5661 if (a[2] != "red") e++;
5664 \begin_layout Plain Layout
5666 if (length(a) != 2) e++;
5669 \begin_layout Plain Layout
5673 chunkref{pca-test.awk:summary}>
5676 \begin_layout Plain Layout
5680 \begin_layout Plain Layout
5682 parse_chunk_args("c-like", "${colour}", a, "");
5685 \begin_layout Plain Layout
5687 if (a[1] != "${colour}") e++;
5690 \begin_layout Plain Layout
5692 if (length(a) != 1) e++;
5695 \begin_layout Plain Layout
5699 chunkref{pca-test.awk:summary}>
5707 \begin_layout Standard
5708 Nested modes are identified by a backslash, a double or single quote, various
5709 bracket styles or a /* comment.
5712 \begin_layout Standard
5713 For each of these sub-modes modes we must also identify at a mode terminator,
5714 and any sub-modes or delimiters that may be entered
5718 \begin_layout Plain Layout
5719 Because we are using the sub-mode characters as the mode identifier it means
5720 we can't currently have a mode character dependant on it's context; i.e.
5722 \begin_inset Flex CharStyle:Code
5725 \begin_layout Plain Layout
5731 can't behave differently when it is inside
5732 \begin_inset Flex CharStyle:Code
5735 \begin_layout Plain Layout
5749 \begin_layout Subsection
5753 \begin_layout Standard
5754 The backslash mode has no submodes or delimiters, and is terminated by any
5756 Note that we are not so much interested in evaluating or interpolating
5757 content as we are in delineating content.
5758 It is no matter that a double backslash (
5759 \begin_inset Flex CharStyle:Code
5762 \begin_layout Plain Layout
5772 ) may represent a single backslash while a backslash-newline may represent
5773 white space, but it does matter that the newline in a backslash newline
5774 should not be able to terminate a C pre-processor statement; and so the
5775 newline will be consumed by the backslash however it is to be interpreted.
5779 common-mode-definitions
5782 \begin_layout Standard
5783 \begin_inset listings
5787 \begin_layout Plain Layout
5789 modes[${language}, "
5793 ", "terminators"]=".";
5801 \begin_layout Subsection
5805 \begin_layout Standard
5806 Common languages support two kinds of strings quoting, double quotes and
5811 mode:common-string,params=language;quote
5814 \begin_layout Standard
5815 In a string we have one special mode, which is the backslash.
5816 This may escape an embedded quote and prevent us thinking that it should
5817 terminate the string.
5821 \begin_layout Standard
5822 \begin_inset listings
5826 \begin_layout Plain Layout
5828 modes[${language}, ${quote}, "submodes" ]="
5844 \begin_layout Standard
5845 Otherwise, the string will be terminated by the same character that commenced
5849 \begin_layout Standard
5850 \begin_inset listings
5854 \begin_layout Plain Layout
5856 modes[${language}, ${quote}, "terminators"]=${quote};
5864 \begin_layout Standard
5865 In C type languages, certain escape sequences exist in strings.
5866 We need to define mechanism to enclode any chunks included in this mode
5867 using those escape sequences.
5868 These are expressed in two parts, s meaning search, and r meaning replace.
5871 \begin_layout Standard
5872 The first substitution is to replace a backslash with a double backslash.
5873 We do this first as other substitutions may introduce a backslash which
5874 we would not then want to escape again here.
5877 \begin_layout Standard
5878 \begin_inset listings
5882 \begin_layout Plain Layout
5884 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
5891 \begin_layout Plain Layout
5893 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
5909 \begin_layout Standard
5910 If the quote character occurs in the text, it should be preceded by a backslash,
5911 otherwise it would terminate the string unexpectedly.
5914 \begin_layout Standard
5915 \begin_inset listings
5919 \begin_layout Plain Layout
5921 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]=${quote};
5924 \begin_layout Plain Layout
5926 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
5938 \begin_layout Standard
5939 Any newlines in the string, must be replaced by
5940 \begin_inset Flex CharStyle:Code
5943 \begin_layout Plain Layout
5954 \begin_layout Standard
5955 \begin_inset listings
5959 \begin_layout Plain Layout
5961 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
5966 \begin_layout Plain Layout
5968 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
5980 \begin_layout Standard
5981 For the common modes, we define this string handling for double and single
5986 common-mode-definitions,params=language
5989 \begin_layout Standard
5990 \begin_inset listings
5994 \begin_layout Plain Layout
5998 chunkref{mode:common-string}(${language}, "
6003 \begin_layout Plain Layout
6007 chunkref{mode:common-string}(${language}, "'")>
6015 \begin_layout Standard
6016 Working strings should pass this test:
6020 test:mode-definitions
6023 \begin_layout Standard
6024 \begin_inset listings
6028 \begin_layout Plain Layout
6030 parse_chunk_args("c-like", "say
6049 \begin_layout Plain Layout
6070 \begin_layout Plain Layout
6072 if (a[2] != "for me") e++;
6075 \begin_layout Plain Layout
6077 if (length(a) != 2) e++;
6080 \begin_layout Plain Layout
6084 chunkref{pca-test.awk:summary}>
6092 \begin_layout Subsection
6093 Parentheses, Braces and Brackets
6096 \begin_layout Standard
6097 Where quotes are closed by the same character, parentheses, brackets and
6098 braces are closed by an alternate character.
6102 mode:common-brackets,params=language;open;close
6105 \begin_layout Standard
6106 \begin_inset listings
6110 \begin_layout Plain Layout
6112 modes[${language}, ${open}, "submodes" ]="
6137 \begin_layout Plain Layout
6139 modes[${language}, ${open}, "delimiters"]=" *, *";
6142 \begin_layout Plain Layout
6144 modes[${language}, ${open}, "terminators"]=${close};
6152 \begin_layout Standard
6153 Note that the open is NOT a regex but the close token IS.
6155 \begin_inset Note Note
6158 \begin_layout Plain Layout
6159 WHen we can quote regex we won't have to put the slashes in here
6168 common-mode-definitions,params=language
6171 \begin_layout Standard
6172 \begin_inset listings
6176 \begin_layout Plain Layout
6180 chunkref{mode:common-brackets}(${language}, "{", "}")>
6183 \begin_layout Plain Layout
6187 chunkref{mode:common-brackets}(${language}, "[", "
6194 \begin_layout Plain Layout
6198 chunkref{mode:common-brackets}(${language}, "(", "
6210 \begin_layout Subsection
6211 Customizing Standard Modes
6215 mode:add-submode,params=language;mode;submode
6218 \begin_layout Standard
6219 \begin_inset listings
6223 \begin_layout Plain Layout
6225 modes[${language}, ${mode}, "submodes"] = modes[${language}, ${mode}, "submodes"
6235 mode:add-escapes,params=language;mode;search;replace
6238 \begin_layout Standard
6239 \begin_inset listings
6243 \begin_layout Plain Layout
6245 escapes[${language}, ${mode}, ++escapes[${language}, ${mode}], "s"]=${search};
6248 \begin_layout Plain Layout
6250 escapes[${language}, ${mode}, escapes[${language}, ${mode}], "r"]=${replace};
6258 \begin_layout Subsection
6262 \begin_layout Standard
6264 \begin_inset Flex CharStyle:Code
6267 \begin_layout Plain Layout
6274 \begin_inset Flex CharStyle:Code
6277 \begin_layout Plain Layout
6283 style comments to be added to any language:
6287 mode:multi-line-comments,params=language
6290 \begin_layout Standard
6291 \begin_inset listings
6295 \begin_layout Plain Layout
6299 chunkref{mode:add-submode}(${language}, "", "/
6306 \begin_layout Plain Layout
6308 modes[${language}, "/*", "terminators"]="
6321 mode:single-line-slash-comments,params=language
6324 \begin_layout Standard
6325 \begin_inset listings
6329 \begin_layout Plain Layout
6333 chunkref{mode:add-submode}(${language}, "", "//")>
6336 \begin_layout Plain Layout
6338 modes[${language}, "//", "terminators"]="
6343 \begin_layout Plain Layout
6347 chunkref{mode:add-escapes}(${language}, "//", "
6349 textbackslash{}n", "
6351 textbackslash{}n//")>
6359 \begin_layout Standard
6361 \begin_inset Flex CharStyle:Code
6364 \begin_layout Plain Layout
6370 style comments (as used in awk and shell scripts) in a similar manner.
6374 mode:add-hash-comments,params=language
6375 \begin_inset Note Note
6378 \begin_layout Plain Layout
6385 and have hacky work-arounds in the parser for now
6393 \begin_layout Standard
6394 \begin_inset listings
6398 \begin_layout Plain Layout
6402 chunkref{mode:add-submode}(${language}, "", "
6407 \begin_layout Plain Layout
6409 modes[${language}, "#", "terminators"]="
6414 \begin_layout Plain Layout
6418 chunkref{mode:add-escapes}(${language}, "
6422 textbackslash{}n", "
6434 \begin_layout Standard
6436 \begin_inset Flex CharStyle:Code
6439 \begin_layout Plain Layout
6445 denotes pre-processor directives which can be multi-line
6449 mode:add-hash-defines,params=language
6452 \begin_layout Standard
6453 \begin_inset listings
6457 \begin_layout Plain Layout
6461 chunkref{mode:add-submode}(${language}, "", "
6466 \begin_layout Plain Layout
6468 modes[${language}, "#", "submodes" ]="
6479 \begin_layout Plain Layout
6481 modes[${language}, "#", "terminators"]="
6486 \begin_layout Plain Layout
6490 chunkref{mode:add-escapes}(${language}, "
6494 textbackslash{}n", "
6512 \begin_layout Standard
6513 We can add these definitions to various languages
6520 \begin_layout Standard
6521 \begin_inset listings
6525 \begin_layout Plain Layout
6529 chunkref{common-mode-definitions}("c-like")>
6532 \begin_layout Plain Layout
6536 \begin_layout Plain Layout
6540 chunkref{common-mode-definitions}("c")>
6543 \begin_layout Plain Layout
6547 chunkref{mode:multi-line-comments}("c")>
6550 \begin_layout Plain Layout
6554 chunkref{mode:single-line-slash-comments}("c")>
6557 \begin_layout Plain Layout
6561 chunkref{mode:add-hash-defines}("c")>
6564 \begin_layout Plain Layout
6568 \begin_layout Plain Layout
6572 chunkref{common-mode-definitions}("awk")>
6575 \begin_layout Plain Layout
6579 chunkref{mode:add-hash-comments}("awk")>
6587 \begin_layout Standard
6588 The awk definitions should allow a comment block like this:
6592 test:comment-quote,language=awk
6595 \begin_layout Standard
6596 \begin_inset listings
6600 \begin_layout Plain Layout
6604 chunkref{test:comment-text}>
6613 test:comment-text,language=
6616 \begin_layout Standard
6617 \begin_inset listings
6621 \begin_layout Plain Layout
6626 \begin_layout Plain Layout
6628 the quick brown fox to bring lemonade
6631 \begin_layout Plain Layout
6641 \begin_layout Standard
6642 to come out like this:
6646 test:comment-quote:result
6649 \begin_layout Standard
6650 \begin_inset listings
6654 \begin_layout Plain Layout
6656 # Comment: Now is the time for
6659 \begin_layout Plain Layout
6661 #the quick brown fox to bring lemonade
6664 \begin_layout Plain Layout
6674 \begin_layout Standard
6675 The C definition for such a block should have it come out like this:
6679 test:comment-quote:C-result
6682 \begin_layout Standard
6683 \begin_inset listings
6687 \begin_layout Plain Layout
6689 # Comment: Now is the time for
6694 \begin_layout Plain Layout
6696 the quick brown fox to bring lemonade
6701 \begin_layout Plain Layout
6711 \begin_layout Section
6715 \begin_layout Standard
6716 Also, the parser must return any spare text at the end that has not been
6717 processed due to a mode terminator being found.
6721 test:mode-definitions
6724 \begin_layout Standard
6725 \begin_inset listings
6729 \begin_layout Plain Layout
6731 rest = parse_chunk_args("c-like", "1, 2, 3) spare", a, "(");
6734 \begin_layout Plain Layout
6739 \begin_layout Plain Layout
6744 \begin_layout Plain Layout
6749 \begin_layout Plain Layout
6751 if (length(a) != 3) e++;
6754 \begin_layout Plain Layout
6756 if (rest != " spare") e++;
6759 \begin_layout Plain Layout
6763 chunkref{pca-test.awk:summary}>
6771 \begin_layout Standard
6772 We must also be able to parse the example given earlier.
6776 test:mode-definitions
6779 \begin_layout Standard
6780 \begin_inset listings
6784 \begin_layout Plain Layout
6786 parse_chunk_args("c-like", "things[x, y], get_other_things(a,
6793 \begin_layout Plain Layout
6795 if (a[1] != "things[x, y]") e++;
6798 \begin_layout Plain Layout
6800 if (a[2] != "get_other_things(a,
6807 \begin_layout Plain Layout
6809 if (a[3] != "99") e++;
6812 \begin_layout Plain Layout
6814 if (length(a) != 3) e++;
6817 \begin_layout Plain Layout
6821 chunkref{pca-test.awk:summary}>
6829 \begin_layout Section
6830 A non-recursive mode tracker
6833 \begin_layout Subsection
6837 \begin_layout Standard
6838 The mode tracker holds its state in a stack based on a hash.
6839 This function, when passed an empty hash will intialize it.
6846 \begin_layout Standard
6847 \begin_inset listings
6851 \begin_layout Plain Layout
6853 function new_mode_tracker(context, language, mode) {
6856 \begin_layout Plain Layout
6861 \begin_layout Plain Layout
6863 context[0, "language"] = language;
6866 \begin_layout Plain Layout
6868 context[0, "mode"] = mode;
6871 \begin_layout Plain Layout
6881 \begin_layout Standard
6882 Because awk functions cannot return an array, we must create the array first
6883 and pass it in, so we have a newfangle macro to do this:
6887 new-mode-tracker,language=awk,params=context;language;mode
6890 \begin_layout Standard
6891 \begin_inset listings
6895 \begin_layout Plain Layout
6899 chunkref{awk-delete-array}(${context})>
6902 \begin_layout Plain Layout
6904 new_mode_tracker(${context}, ${language}, ${mode});
6912 \begin_layout Subsection
6916 \begin_layout Standard
6917 And for tracking modes, we dispatch to a mode-tracker action based on the
6922 mode_tracker,language=awk
6925 \begin_layout Standard
6926 \begin_inset listings
6930 \begin_layout Plain Layout
6932 function push_mode_tracker(context, language, mode,
6935 \begin_layout Plain Layout
6940 \begin_layout Plain Layout
6945 \begin_layout Plain Layout
6950 \begin_layout Plain Layout
6952 if (! ("" in context)) {
6955 \begin_layout Plain Layout
6959 chunkref{new-mode-tracker}(context, language, mode)>
6962 \begin_layout Plain Layout
6967 \begin_layout Plain Layout
6972 \begin_layout Plain Layout
6974 if (context[top, "language"] == language && mode=="") mode = context[top,
6978 \begin_layout Plain Layout
6983 \begin_layout Plain Layout
6985 context[top, "language"] = language;
6988 \begin_layout Plain Layout
6990 context[top, "mode"] = mode;
6993 \begin_layout Plain Layout
6998 \begin_layout Plain Layout
7003 \begin_layout Plain Layout
7013 \begin_layout Standard
7014 \begin_inset listings
7018 \begin_layout Plain Layout
7020 function finalize_mode_tracker(context)
7023 \begin_layout Plain Layout
7028 \begin_layout Plain Layout
7030 if ( ("" in context) && context[""] != 0) return 0;
7033 \begin_layout Plain Layout
7038 \begin_layout Plain Layout
7048 \begin_layout Standard
7049 This implies that any chunk must be syntactically whole; for instance, this
7057 \begin_layout Standard
7058 \begin_inset listings
7062 \begin_layout Plain Layout
7067 \begin_layout Plain Layout
7071 chunkref{test:say-hello}>
7074 \begin_layout Plain Layout
7088 \begin_layout Standard
7089 \begin_inset listings
7093 \begin_layout Plain Layout
7103 \begin_layout Standard
7104 But this is not fine; the chunk
7105 \begin_inset Flex Chunkref
7108 \begin_layout Plain Layout
7114 is not properly cromulent.
7121 \begin_layout Standard
7122 \begin_inset listings
7126 \begin_layout Plain Layout
7131 \begin_layout Plain Layout
7135 chunkref{test:hidden-else}>
7138 \begin_layout Plain Layout
7152 \begin_layout Standard
7153 \begin_inset listings
7157 \begin_layout Plain Layout
7162 \begin_layout Plain Layout
7167 \begin_layout Plain Layout
7177 \begin_layout Standard
7178 These tests will check for correct behaviour:
7185 \begin_layout Standard
7186 \begin_inset listings
7190 \begin_layout Plain Layout
7192 echo Cromulence test
7195 \begin_layout Plain Layout
7197 passtest $NEWFANGLE -Rtest:whole-chunk $TEX_SRC &>/dev/null || ( echo "Whole
7198 chunk failed" && exit 1 )
7201 \begin_layout Plain Layout
7203 failtest $NEWFANGLE -Rtest:partial-chunk $TEX_SRC &>/dev/null || ( echo
7204 "Partial chunk failed" && exit 1 )
7212 \begin_layout Subsection
7216 \begin_layout Standard
7217 We must avoid recursion as a language construct because we intend to employ
7218 mode-tracking to track language mode of emitted code, and the code is emitted
7219 from a function which is itself recursive, so instead we implement psuedo-recur
7220 sion using our own stack based on a hash.
7227 \begin_layout Standard
7228 \begin_inset listings
7232 \begin_layout Plain Layout
7234 function mode_tracker(context, text, values,
7237 \begin_layout Plain Layout
7239 # optional parameters
7242 \begin_layout Plain Layout
7247 \begin_layout Plain Layout
7249 mode, submodes, language,
7252 \begin_layout Plain Layout
7254 cindex, c, a, part, item, name, result, new_values, new_mode,
7257 \begin_layout Plain Layout
7259 delimiters, terminators)
7262 \begin_layout Plain Layout
7272 \begin_layout Standard
7273 We could be re-commencing with a valid context, so we need to setup the
7274 state according to the last context.
7277 \begin_layout Standard
7278 \begin_inset listings
7282 \begin_layout Plain Layout
7284 cindex = context[""] + 0;
7287 \begin_layout Plain Layout
7289 mode = context[cindex, "mode"];
7292 \begin_layout Plain Layout
7294 language = context[cindex, "language" ];
7302 \begin_layout Standard
7303 First we construct a single large regex combining the possible sub-modes
7304 for the current mode along with the terminators for the current mode.
7308 parse_chunk_args-reset-modes
7311 \begin_layout Standard
7312 \begin_inset listings
7316 \begin_layout Plain Layout
7318 submodes=modes[language, mode, "submodes"];
7321 \begin_layout Plain Layout
7325 \begin_layout Plain Layout
7327 if ((language, mode, "delimiters") in modes) {
7330 \begin_layout Plain Layout
7332 delimiters = modes[language, mode, "delimiters"];
7335 \begin_layout Plain Layout
7337 if (length(submodes)>0) submodes = submodes "|";
7340 \begin_layout Plain Layout
7342 submodes=submodes delimiters;
7345 \begin_layout Plain Layout
7347 } else delimiters="";
7350 \begin_layout Plain Layout
7352 if ((language, mode, "terminators") in modes) {
7355 \begin_layout Plain Layout
7357 terminators = modes[language, mode, "terminators"];
7360 \begin_layout Plain Layout
7362 if (length(submodes)>0) submodes = submodes "|";
7365 \begin_layout Plain Layout
7367 submodes=submodes terminators;
7370 \begin_layout Plain Layout
7372 } else terminators="";
7380 \begin_layout Standard
7381 If we don't find anything to match on --- probably because the language
7382 is not supported --- then we return the entire text without matching anything.
7385 \begin_layout Standard
7386 \begin_inset listings
7390 \begin_layout Plain Layout
7392 if (! length(submodes)) return text;
7404 \begin_layout Standard
7405 \begin_inset listings
7409 \begin_layout Plain Layout
7413 chunkref{parse_chunk_args-reset-modes}>
7421 \begin_layout Standard
7422 We then iterate the text (until there is none left) looking for sub-modes
7423 or terminators in the regex.
7426 \begin_layout Standard
7427 \begin_inset listings
7431 \begin_layout Plain Layout
7433 while((cindex >= 0) && length(text)) {
7436 \begin_layout Plain Layout
7438 if (match(text, "(" submodes ")", a)) {
7446 \begin_layout Standard
7447 A bug that creeps in regularly during development is bad regexes of zero
7448 length which result in an infinite loop (as no text is consumed), so I
7449 catch that right away with this test.
7452 \begin_layout Standard
7453 \begin_inset listings
7457 \begin_layout Plain Layout
7462 \begin_layout Plain Layout
7464 error(sprintf("Internal error, matched zero length submode, should
7465 be impossible - likely regex computation error
7472 \begin_layout Plain Layout
7480 n", language, mode, submodes));
7483 \begin_layout Plain Layout
7493 \begin_layout Standard
7494 \begin_inset Flex CharStyle:Code
7497 \begin_layout Plain Layout
7503 is defined as the text up to the sub-mode or terminator, and this is appended
7505 \begin_inset Flex CharStyle:Code
7508 \begin_layout Plain Layout
7514 --- which is the current text being gathered.
7515 If a mode has a delimiter, then item is reset each time a delimiter is
7519 \begin_layout Standard
7520 \begin_inset Formula $\mathtt{\overbrace{"\overbrace{hello}^{item},\ \overbrace{there}^{item}"}^{item},\ \overbrace{he\ said.}^{item}}$
7526 \begin_layout Standard
7527 \begin_inset listings
7531 \begin_layout Plain Layout
7533 part = substr(text, 1, RSTART -1);
7536 \begin_layout Plain Layout
7546 \begin_layout Standard
7547 We must now determine what was matched.
7548 If it was a terminator, then we must restore the previous mode.
7551 \begin_layout Standard
7552 \begin_inset listings
7556 \begin_layout Plain Layout
7558 if (match(a[1], "^" terminators "$")) {
7561 \begin_layout Plain Layout
7563 #printf("%2d EXIT MODE [%s] by [%s] [%s]
7565 n", cindex, mode, a[1], text) > "/dev/stderr"
7568 \begin_layout Plain Layout
7570 context[cindex, "values", ++context[cindex, "values"]] = item;
7573 \begin_layout Plain Layout
7575 delete context[cindex];
7578 \begin_layout Plain Layout
7580 context[""] = --cindex;
7583 \begin_layout Plain Layout
7588 \begin_layout Plain Layout
7590 mode = context[cindex, "mode"];
7593 \begin_layout Plain Layout
7595 language = context[cindex, "language"];
7598 \begin_layout Plain Layout
7602 chunkref{parse_chunk_args-reset-modes}>
7605 \begin_layout Plain Layout
7610 \begin_layout Plain Layout
7615 \begin_layout Plain Layout
7617 text = substr(text, 1 + length(part) + length(a[1]));
7620 \begin_layout Plain Layout
7630 \begin_layout Standard
7631 If a delimiter was matched, then we must store the current item in the parsed
7632 values array, and reset the item.
7635 \begin_layout Standard
7636 \begin_inset listings
7640 \begin_layout Plain Layout
7642 else if (match(a[1], "^" delimiters "$")) {
7645 \begin_layout Plain Layout
7650 \begin_layout Plain Layout
7652 context[cindex, "values", ++context[cindex, "values"]] = item;
7655 \begin_layout Plain Layout
7660 \begin_layout Plain Layout
7665 \begin_layout Plain Layout
7670 \begin_layout Plain Layout
7675 \begin_layout Plain Layout
7677 text = substr(text, 1 + length(part) + length(a[1]));
7680 \begin_layout Plain Layout
7690 \begin_layout Standard
7691 otherwise, if a new submode is detected (all submodes have terminators),
7692 we must create a nested parse context until we find the terminator for
7696 \begin_layout Standard
7697 \begin_inset listings
7701 \begin_layout Plain Layout
7703 else if ((language, a[1], "terminators") in modes) {
7706 \begin_layout Plain Layout
7708 #check if new_mode is defined
7711 \begin_layout Plain Layout
7716 \begin_layout Plain Layout
7718 #printf("%2d ENTER MODE [%s] in [%s]
7720 n", cindex, a[1], text) > "/dev/stderr"
7723 \begin_layout Plain Layout
7725 text = substr(text, 1 + length(part) + length(a[1]));
7728 \begin_layout Plain Layout
7730 context[""] = ++cindex;
7733 \begin_layout Plain Layout
7735 context[cindex, "mode"] = a[1];
7738 \begin_layout Plain Layout
7740 context[cindex, "language"] = language;
7743 \begin_layout Plain Layout
7748 \begin_layout Plain Layout
7752 chunkref{parse_chunk_args-reset-modes}>
7755 \begin_layout Plain Layout
7760 \begin_layout Plain Layout
7762 error(sprintf("Submode '%s' set unknown mode in text: %s
7764 nLanguage %s Mode %s
7766 n", a[1], text, language, mode));
7769 \begin_layout Plain Layout
7771 text = substr(text, 1 + length(part) + length(a[1]));
7774 \begin_layout Plain Layout
7779 \begin_layout Plain Layout
7789 \begin_layout Standard
7790 In the final case, we parsed to the end of the string.
7791 If the string was entire, then we should have no nested mode context, but
7792 if the string was just a fragment we may have a mode context which must
7793 be preserved for the next fragment.
7794 Todo: Consideration ought to be given if sub-mode strings are split over
7796 \begin_inset Note Note
7799 \begin_layout Plain Layout
7800 Consideration ought to be given if sub-mode strings are split over two fragments.
7808 \begin_layout Standard
7809 \begin_inset listings
7813 \begin_layout Plain Layout
7818 \begin_layout Plain Layout
7820 context[cindex, "values", ++context[cindex, "values"]] = item text;
7823 \begin_layout Plain Layout
7828 \begin_layout Plain Layout
7833 \begin_layout Plain Layout
7838 \begin_layout Plain Layout
7843 \begin_layout Plain Layout
7847 \begin_layout Plain Layout
7849 context["item"] = item;
7852 \begin_layout Plain Layout
7856 \begin_layout Plain Layout
7858 if (length(item)) context[cindex, "values", ++context[cindex, "values"]]
7862 \begin_layout Plain Layout
7867 \begin_layout Plain Layout
7877 \begin_layout Subsubsection
7881 \begin_layout Standard
7882 All the mode tracker chunks are referred to here:
7889 \begin_layout Standard
7890 \begin_inset listings
7894 \begin_layout Plain Layout
7898 chunkref{new_mode_tracker()}>
7901 \begin_layout Plain Layout
7905 chunkref{mode_tracker()}>
7913 \begin_layout Subsubsection
7917 \begin_layout Standard
7918 We can test this function like this:
7922 pca-test.awk,language=awk
7925 \begin_layout Standard
7926 \begin_inset listings
7930 \begin_layout Plain Layout
7937 \begin_layout Plain Layout
7941 chunkref{mode-tracker}>
7944 \begin_layout Plain Layout
7948 chunkref{parse_chunk_args()}>
7951 \begin_layout Plain Layout
7956 \begin_layout Plain Layout
7961 \begin_layout Plain Layout
7965 chunkref{mode-definitions}>
7968 \begin_layout Plain Layout
7972 \begin_layout Plain Layout
7976 chunkref{test:mode-definitions}>
7979 \begin_layout Plain Layout
7990 pca-test.awk:summary,language=awk
7993 \begin_layout Standard
7994 \begin_inset listings
7998 \begin_layout Plain Layout
8003 \begin_layout Plain Layout
8008 \begin_layout Plain Layout
8013 \begin_layout Plain Layout
8015 print "a[" b "] => " a[b];
8018 \begin_layout Plain Layout
8023 \begin_layout Plain Layout
8028 \begin_layout Plain Layout
8033 \begin_layout Plain Layout
8038 \begin_layout Plain Layout
8043 \begin_layout Plain Layout
8053 \begin_layout Standard
8054 which should give this output:
8058 pca-test.awk-results,language=
8061 \begin_layout Standard
8062 \begin_inset listings
8066 \begin_layout Plain Layout
8068 a[foo.quux.quirk] =>
8071 \begin_layout Plain Layout
8073 a[foo.quux.a] => fleeg
8076 \begin_layout Plain Layout
8081 \begin_layout Plain Layout
8086 \begin_layout Plain Layout
8096 \begin_layout Section
8097 Escaping and Quoting
8100 \begin_layout Standard
8101 Each nested mode can optionally define a set of transforms to be applied
8102 to any text that is included from another language.
8105 \begin_layout Standard
8106 This code can perform transforms
8110 mode_tracker,language=awk
8113 \begin_layout Standard
8114 \begin_inset listings
8118 \begin_layout Plain Layout
8120 function transform_escape(s, r, text,
8123 \begin_layout Plain Layout
8128 \begin_layout Plain Layout
8133 \begin_layout Plain Layout
8138 \begin_layout Plain Layout
8143 \begin_layout Plain Layout
8148 \begin_layout Plain Layout
8150 for(c=1; c <= max && (c in s); c++) {
8153 \begin_layout Plain Layout
8155 gsub(s[c], r[c], text);
8158 \begin_layout Plain Layout
8163 \begin_layout Plain Layout
8168 \begin_layout Plain Layout
8178 \begin_layout Standard
8179 This function must append from index
8180 \begin_inset Flex CharStyle:Code
8183 \begin_layout Plain Layout
8189 onwards, and escape transforms from the supplied context, and return c
8190 + number of new transforms.
8193 \begin_layout Standard
8194 \begin_inset listings
8198 \begin_layout Plain Layout
8200 function mode_escaper(context, s, r, src,
8203 \begin_layout Plain Layout
8208 \begin_layout Plain Layout
8213 \begin_layout Plain Layout
8215 for(c = context[""]; c >= 0; c--) {
8218 \begin_layout Plain Layout
8220 if ( (context[c, "language"], context[c, "mode"]) in escapes) {
8223 \begin_layout Plain Layout
8225 cpl = escapes[context[c, "language"], context[c, "mode"]];
8228 \begin_layout Plain Layout
8230 for (cp = 1; cp <= cpl; cp ++) {
8233 \begin_layout Plain Layout
8238 \begin_layout Plain Layout
8240 s[src] = escapes[context[c, "language"], context[c, "mode"], c, "s"];
8243 \begin_layout Plain Layout
8245 r[src] = escapes[context[c, "language"], context[c, "mode"], c, "r"];
8248 \begin_layout Plain Layout
8253 \begin_layout Plain Layout
8258 \begin_layout Plain Layout
8263 \begin_layout Plain Layout
8268 \begin_layout Plain Layout
8279 test:escapes,language=sh
8282 \begin_layout Standard
8283 \begin_inset listings
8287 \begin_layout Plain Layout
8292 \begin_layout Plain Layout
8294 passtest $NEWFANGLE -Rtest:comment-quote $TEX_SRC &>/dev/null || ( echo
8295 "Comment-quote failed" && exit 1 )
8303 \begin_layout Chapter
8307 \begin_layout Standard
8308 Newfangle recognizes noweb chunks, but as we also want better LaTeX integration
8309 we will recognize any of these:
8312 \begin_layout Itemize
8313 notangle chunks matching the pattern
8314 \begin_inset Flex CharStyle:Code
8317 \begin_layout Plain Layout
8319 \begin_inset space \hspace*{}
8324 \begin_inset space \hspace*{}
8336 \begin_layout Itemize
8337 a chunks beginning with
8338 \begin_inset Flex CharStyle:Code
8341 \begin_layout Plain Layout
8351 Chunk{\SpecialChar \ldots{}
8352 } on the previous line
8355 \begin_layout Itemize
8356 an older form I have used, beginning with
8357 \begin_inset Flex CharStyle:Code
8360 \begin_layout Plain Layout
8363 begin{Chunk}[options]
8368 --- also more suitable for plain LaTeX users
8372 \begin_layout Plain Layout
8373 Is there such a thing as plain LaTeX?
8381 \begin_layout Section
8385 \begin_layout Standard
8387 \begin_inset Flex CharStyle:Code
8390 \begin_layout Plain Layout
8396 is used to signify that we are processing a code chunk and not document.
8397 In such a state, input lines will be assigned to the current chunk; otherwise
8401 \begin_layout Subsection
8405 \begin_layout Standard
8406 Our current scheme is to recognize the new lstlisting chunks, but these
8407 may be preceded by a
8408 \begin_inset Flex CharStyle:Code
8411 \begin_layout Plain Layout
8419 command which in LyX is a more convenient way to pass the chunk name to
8421 \begin_inset Flex CharStyle:Code
8424 \begin_layout Plain Layout
8432 command, and a more visible way to specify other
8433 \begin_inset Flex CharStyle:Code
8436 \begin_layout Plain Layout
8445 \begin_layout Standard
8446 The arguments to the
8447 \begin_inset Flex CharStyle:Code
8450 \begin_layout Plain Layout
8458 command are a name, and then a comma-seperated list of key-value pairs
8460 \begin_inset Flex CharStyle:Code
8463 \begin_layout Plain Layout
8472 (In fact within the LaTeX
8473 \begin_inset Flex CharStyle:Code
8476 \begin_layout Plain Layout
8485 \begin_inset CommandInset ref
8487 reference "sub:The-chunk-command"
8492 \begin_inset Flex CharStyle:Code
8495 \begin_layout Plain Layout
8501 is prefixed to the argument which is then literally passed to
8502 \begin_inset Flex CharStyle:Code
8505 \begin_layout Plain Layout
8517 recognize-chunk,language=awk
8520 \begin_layout Standard
8521 \begin_inset listings
8525 \begin_layout Plain Layout
8534 \begin_layout Plain Layout
8544 Chunk{ *([^ ,}]*),?(.*)}", line)) {
8547 \begin_layout Plain Layout
8549 next_chunk_name = line[1];
8552 \begin_layout Plain Layout
8554 get_chunk_args(line[2], next_chunk_args);
8557 \begin_layout Plain Layout
8562 \begin_layout Plain Layout
8567 \begin_layout Plain Layout
8577 \begin_layout Standard
8578 We also make a basic attempt to parse the name out of the
8579 \begin_inset Flex CharStyle:Code
8582 \begin_layout Plain Layout
8586 \begin_inset space \hspace{}
8595 text, otherwise we fall back to the name found in the previous chunk command.
8596 This attempt is very basic and doesn't support commas or spaces or square
8597 brackets as part of the chunkname.
8599 \begin_inset Flex CharStyle:Code
8602 \begin_layout Plain Layout
8610 which is convenient for some users
8614 \begin_layout Plain Layout
8615 but not yet supported in the LaTeX macros
8621 \begin_inset Note Note
8624 \begin_layout Plain Layout
8633 \begin_layout Standard
8634 \begin_inset listings
8638 \begin_layout Plain Layout
8651 \begin_layout Plain Layout
8653 if (match($0, "}.*[[,] *name= *{? *([^], }]*)", line)) {
8656 \begin_layout Plain Layout
8661 \begin_layout Plain Layout
8666 \begin_layout Plain Layout
8668 new_chunk(next_chunk_name, next_chunk_args);
8671 \begin_layout Plain Layout
8676 \begin_layout Plain Layout
8681 \begin_layout Plain Layout
8686 \begin_layout Plain Layout
8696 \begin_layout Subsection
8700 \begin_layout Standard
8701 We recognize notangle style chunks too:
8705 recognize-chunk,language=awk
8708 \begin_layout Standard
8709 \begin_inset listings
8713 \begin_layout Plain Layout
8718 \begin_layout Plain Layout
8720 if (match($0, "^[<]<(.*)[>]>= *$", line)) {
8723 \begin_layout Plain Layout
8728 \begin_layout Plain Layout
8733 \begin_layout Plain Layout
8738 \begin_layout Plain Layout
8743 \begin_layout Plain Layout
8748 \begin_layout Plain Layout
8758 \begin_layout Section
8762 \begin_layout Standard
8763 Likewise, we need to recognize when a chunk ends.
8766 \begin_layout Subsection
8770 \begin_layout Standard
8772 \begin_inset Flex CharStyle:Code
8775 \begin_layout Plain Layout
8782 \begin_inset Flex CharStyle:Code
8785 \begin_layout Plain Layout
8791 is surrounded by square brackets so that when this document is processed,
8792 this chunk doesn't terminate early when the lstlistings package recognizes
8793 it's own end-string!
8794 \begin_inset Note Greyedout
8797 \begin_layout Plain Layout
8798 This doesn't make sense as the regex is anchored with ^, which this line
8799 does not begin with!
8805 \begin_inset Note Note
8808 \begin_layout Plain Layout
8821 \begin_layout Standard
8822 \begin_inset listings
8826 \begin_layout Plain Layout
8839 \begin_layout Plain Layout
8844 \begin_layout Plain Layout
8849 \begin_layout Plain Layout
8854 \begin_layout Plain Layout
8864 \begin_layout Subsection
8872 \begin_layout Standard
8873 \begin_inset listings
8877 \begin_layout Plain Layout
8882 \begin_layout Plain Layout
8887 \begin_layout Plain Layout
8892 \begin_layout Plain Layout
8902 \begin_layout Standard
8903 All other recognizers are only of effect if we are chunking; there's no
8904 point in looking at lines if they aren't part of a chunk, so we just ignore
8905 them as efficiently as we can.
8912 \begin_layout Standard
8913 \begin_inset listings
8917 \begin_layout Plain Layout
8919 ! chunking { next; }
8927 \begin_layout Section
8931 \begin_layout Standard
8932 Chunk contents are any lines read while
8933 \begin_inset Flex CharStyle:Code
8936 \begin_layout Plain Layout
8943 Some chunk contents are special in that they refer to other chunks, and
8944 will be replaced by the contents of these chunks when the file is generated.
8947 \begin_layout Standard
8948 \begin_inset CommandInset label
8950 name "sub:ORS-chunk-text"
8954 We add the output record separator
8955 \begin_inset Flex CharStyle:Code
8958 \begin_layout Plain Layout
8964 to the line now, because we will set
8965 \begin_inset Flex CharStyle:Code
8968 \begin_layout Plain Layout
8974 to the empty string when we generate the output
8978 \begin_layout Plain Layout
8979 So that we can print partial lines using
8980 \begin_inset Flex CharStyle:Code
8983 \begin_layout Plain Layout
8990 \begin_inset Flex CharStyle:Code
8993 \begin_layout Plain Layout
9011 \begin_layout Standard
9012 \begin_inset listings
9016 \begin_layout Plain Layout
9018 length(active_chunk) {
9021 \begin_layout Plain Layout
9025 chunkref{process-chunk-tabs}>
9028 \begin_layout Plain Layout
9032 chunkref{process-chunk}>
9035 \begin_layout Plain Layout
9045 \begin_layout Standard
9046 If a chunk just consisted of plain text, we could handle the chunk like
9051 process-chunk-simple
9054 \begin_layout Standard
9055 \begin_inset listings
9059 \begin_layout Plain Layout
9061 chunk_line(active_chunk, $0 ORS);
9069 \begin_layout Standard
9070 but in fact a chunk can include references to other chunks.
9071 Chunk includes are traditionally written as
9072 \begin_inset Flex CharStyle:Code
9075 \begin_layout Plain Layout
9081 , but we support other variations.
9084 \begin_layout Standard
9085 However, we also process tabs at this point, a tab at input can be replaced
9086 by a number of spaces defined by the
9087 \begin_inset Flex CharStyle:Code
9090 \begin_layout Plain Layout
9096 variable, set by the
9097 \begin_inset Flex CharStyle:Code
9100 \begin_layout Plain Layout
9107 Of course this is poor tab behaviour, we should probably have the option
9108 to use proper counted tab-stops and process this on output.
9115 \begin_layout Standard
9116 \begin_inset listings
9120 \begin_layout Plain Layout
9125 \begin_layout Plain Layout
9132 \begin_layout Plain Layout
9142 \begin_layout Subsection
9143 \begin_inset CommandInset label
9145 name "sub:lstlistings-includes"
9152 \begin_layout Standard
9154 \begin_inset Flex CharStyle:Code
9157 \begin_layout Plain Layout
9160 lstset{escapeinside={=<}{>}}
9165 is set, then we can use
9166 \begin_inset Flex CharStyle:Code
9169 \begin_layout Plain Layout
9173 \begin_inset space \hspace{}
9184 \begin_inset Flex CharStyle:Code
9187 \begin_layout Plain Layout
9196 \begin_layout Enumerate
9197 it is a better mnemonic than
9198 \begin_inset Flex CharStyle:Code
9201 \begin_layout Plain Layout
9207 in that the = sign signifies equivalent or substitutability,
9210 \begin_layout Enumerate
9211 and because =< is not valid in C or in any language I can think of
9214 \begin_layout Enumerate
9215 and also because lstlistings doesn't like
9216 \begin_inset Flex CharStyle:Code
9219 \begin_layout Plain Layout
9225 as an end delimiter for the
9229 escape, so we must make do with a single
9230 \begin_inset Flex CharStyle:Code
9233 \begin_layout Plain Layout
9239 , which is better matched by
9240 \begin_inset Flex CharStyle:Code
9243 \begin_layout Plain Layout
9250 \begin_inset Flex CharStyle:Code
9253 \begin_layout Plain Layout
9262 \begin_layout Standard
9264 \begin_inset Note Note
9267 \begin_layout Plain Layout
9274 \begin_inset Flex CharStyle:Code
9277 \begin_layout Plain Layout
9278 =<\SpecialChar \ldots{}
9284 that we use re-enters a LaTeX parsing mode in which some characters are
9287 \begin_inset Flex CharStyle:Code
9290 \begin_layout Plain Layout
9298 , and so these cause trouble if used in arguments to
9299 \begin_inset Flex CharStyle:Code
9302 \begin_layout Plain Layout
9311 At some point I must fix the LaTeX command
9312 \begin_inset Flex CharStyle:Code
9315 \begin_layout Plain Layout
9323 so that it can accept these literally, but until then, when writing chunkref
9324 argumemts that need these characters, I must use the forms
9325 \begin_inset Flex CharStyle:Code
9328 \begin_layout Plain Layout
9337 \begin_inset Flex CharStyle:Code
9340 \begin_layout Plain Layout
9348 ; so I also define a hacky chunk
9349 \begin_inset Flex CharStyle:Code
9352 \begin_layout Plain Layout
9358 whose purpose it is to remove these from any arguments parsed by newfangle,
9359 and used further on.
9366 \begin_layout Standard
9367 \begin_inset listings
9371 \begin_layout Plain Layout
9376 \begin_layout Plain Layout
9389 \begin_layout Plain Layout
9411 \begin_layout Standard
9412 As each chunk line may contain more than one chunk include, we will split
9413 out chunk includes in an iterative fashion
9417 \begin_layout Plain Layout
9418 Contrary to our use of
9419 \begin_inset Flex CharStyle:Code
9422 \begin_layout Plain Layout
9428 when substituting parameters in chapter
9429 \begin_inset CommandInset ref
9431 reference "Here-we-split"
9443 \begin_layout Standard
9444 First, as long as the chunk contains a
9445 \begin_inset Flex CharStyle:Code
9448 \begin_layout Plain Layout
9456 command we take as much as we can up to the first
9457 \begin_inset Flex CharStyle:Code
9460 \begin_layout Plain Layout
9475 \begin_layout Standard
9476 \begin_inset listings
9480 \begin_layout Plain Layout
9485 \begin_layout Plain Layout
9490 \begin_layout Plain Layout
9495 \begin_layout Plain Layout
9513 )|)>|<<([a-zA-Z_][-a-zA-Z0-9_]*)>>)",
9516 \begin_layout Plain Layout
9523 \begin_layout Plain Layout
9528 \begin_layout Plain Layout
9530 chunklet = substr(chunk, 1, RSTART - 1);
9538 \begin_layout Standard
9539 We keep track of the indent count, by counting the number of literal characters
9541 We can then preserve this indent on each output line when multi-line chunks
9545 \begin_layout Standard
9546 We then process this first part literal text, and set the chunk which is
9547 still to be processed to be the text after the
9548 \begin_inset Flex CharStyle:Code
9551 \begin_layout Plain Layout
9559 command, which we will process next as we continue around the loop.
9562 \begin_layout Standard
9563 \begin_inset listings
9567 \begin_layout Plain Layout
9569 indent += length(chunklet);
9572 \begin_layout Plain Layout
9574 chunk_line(active_chunk, chunklet);
9577 \begin_layout Plain Layout
9579 chunk = substr(chunk, RSTART + RLENGTH);
9587 \begin_layout Standard
9588 We then consider the type of chunk command we have found, whether it is
9589 the newfangle style command beginning with
9590 \begin_inset Flex CharStyle:Code
9593 \begin_layout Plain Layout
9599 or the older notangle style beginning with
9600 \begin_inset Flex CharStyle:Code
9603 \begin_layout Plain Layout
9613 \begin_layout Standard
9614 Newfangle chunks may have parameters contained within square brackets.
9615 These will be matched in
9616 \begin_inset Flex CharStyle:Code
9619 \begin_layout Plain Layout
9625 and are considered at this stage of processing to be part of the name of
9626 the chunk to be included.
9629 \begin_layout Standard
9630 \begin_inset listings
9634 \begin_layout Plain Layout
9636 if (substr(line[1], 1, 1) == "=") {
9639 \begin_layout Plain Layout
9641 # chunk name up to }
9644 \begin_layout Plain Layout
9648 chunkref{delatex}(line[3])>
9651 \begin_layout Plain Layout
9653 chunk_include(active_chunk, line[2] line[3], indent);
9656 \begin_layout Plain Layout
9658 } else if (substr(line[1], 1, 1) == "<") {
9661 \begin_layout Plain Layout
9663 chunk_include(active_chunk, line[4], indent);
9666 \begin_layout Plain Layout
9671 \begin_layout Plain Layout
9673 error("Unknown chunk fragment: " line[1]);
9676 \begin_layout Plain Layout
9686 \begin_layout Standard
9687 The loop will continue until there are no more chunkref statements in the
9688 text, at which point we process the final part of the chunk.
9691 \begin_layout Standard
9692 \begin_inset listings
9696 \begin_layout Plain Layout
9701 \begin_layout Plain Layout
9703 chunk_line(active_chunk, chunk);
9711 \begin_layout Standard
9712 \begin_inset CommandInset label
9718 We add the newline character as a chunklet on it's own, to make it easier
9719 to detect new lines and thus manage indentation when processing the output.
9722 \begin_layout Standard
9723 \begin_inset listings
9727 \begin_layout Plain Layout
9729 chunk_line(active_chunk, "
9739 \begin_layout Standard
9740 We will also permit a chunk-part number to follow in square brackets, so
9742 \begin_inset Flex CharStyle:Code
9745 \begin_layout Plain Layout
9748 chunkref{chunk-name[1]}>
9753 will refer to the first part only.
9754 This can make it easy to include a C function prototype in a header file,
9755 if the first part of the chunk is just the function prototype without the
9756 trailing semi-colon.
9757 The header file would include the prototype with the trailing semi-colon,
9761 \begin_layout LyX-Code
9764 chunkref{chunk-name[1]}>;
9767 \begin_layout Standard
9768 This is handled in section
9769 \begin_inset CommandInset ref
9771 reference "sub:Chunk-parts"
9778 \begin_layout Standard
9779 We should perhaps introduce a notion of language specific chunk options;
9780 so that perhaps we could specify:
9783 \begin_layout LyX-Code
9786 chunkref{chunk-name[function-declaration]}>;
9789 \begin_layout Standard
9790 which applies a transform
9791 \begin_inset Flex CharStyle:Code
9794 \begin_layout Plain Layout
9795 function-declaration
9800 to the chunk --- which in this case would extract a function prototype
9802 \begin_inset Note Note
9805 \begin_layout Plain Layout
9814 \begin_layout Chapter
9818 \begin_layout Standard
9819 At the start, first we set the default options.
9826 \begin_layout Standard
9827 \begin_inset listings
9831 \begin_layout Plain Layout
9836 \begin_layout Plain Layout
9841 \begin_layout Plain Layout
9846 \begin_layout Plain Layout
9851 \begin_layout Plain Layout
9861 \begin_layout Standard
9862 Then we use getopt the standard way, and null out ARGV afterwards in the
9870 \begin_layout Standard
9871 \begin_inset listings
9875 \begin_layout Plain Layout
9877 Optind = 1 # skip ARGV[0]
9880 \begin_layout Plain Layout
9882 while(getopt(ARGC, ARGV, "R:LdT:hr")!=-1) {
9885 \begin_layout Plain Layout
9889 chunkref{handle-options}>
9892 \begin_layout Plain Layout
9897 \begin_layout Plain Layout
9899 for (i=1; i<Optind; i++) { ARGV[i]=""; }
9907 \begin_layout Standard
9908 This is how we handle our options:
9915 \begin_layout Standard
9916 \begin_inset listings
9920 \begin_layout Plain Layout
9922 if (Optopt == "R") root = Optarg;
9925 \begin_layout Plain Layout
9927 else if (Optopt == "r") root="";
9930 \begin_layout Plain Layout
9932 else if (Optopt == "L") linenos = 1;
9935 \begin_layout Plain Layout
9937 else if (Optopt == "d") debug = 1;
9940 \begin_layout Plain Layout
9942 else if (Optopt == "T") tabs = indent_string(Optarg+0);
9945 \begin_layout Plain Layout
9947 else if (Optopt == "h") help();
9950 \begin_layout Plain Layout
9952 else if (Optopt == "?") help();
9960 \begin_layout Standard
9961 We do all of this at the beginning of the program
9968 \begin_layout Standard
9969 \begin_inset listings
9973 \begin_layout Plain Layout
9978 \begin_layout Plain Layout
9982 chunkref{constants}>
9985 \begin_layout Plain Layout
9989 chunkref{mode-definitions}>
9992 \begin_layout Plain Layout
9996 chunkref{default-options}>
9999 \begin_layout Plain Layout
10003 \begin_layout Plain Layout
10007 chunkref{read-options}>
10010 \begin_layout Plain Layout
10020 \begin_layout Standard
10021 And have a simple help function
10024 \begin_layout Chunk
10028 \begin_layout Standard
10029 \begin_inset listings
10033 \begin_layout Plain Layout
10038 \begin_layout Plain Layout
10043 \begin_layout Plain Layout
10045 print " newfangle [-L] -R<rootname> [source.tex ...]"
10048 \begin_layout Plain Layout
10050 print " newfangle -r [source.tex ...]"
10053 \begin_layout Plain Layout
10055 print " If the filename, source.tex is not specified then stdin is used"
10058 \begin_layout Plain Layout
10063 \begin_layout Plain Layout
10065 print "-L causes the C statement: #line <lineno>
10072 \begin_layout Plain Layout
10074 print "-R causes the named root to be written to stdout"
10077 \begin_layout Plain Layout
10079 print "-r lists all roots in the file (even those used elsewhere)"
10082 \begin_layout Plain Layout
10087 \begin_layout Plain Layout
10097 \begin_layout Chapter
10098 Generating the output
10101 \begin_layout Standard
10102 We generate output by calling output_chunk, or listing the chunk names.
10105 \begin_layout Chunk
10109 \begin_layout Standard
10110 \begin_inset listings
10114 \begin_layout Plain Layout
10116 if (length(root)) output_chunk(root);
10119 \begin_layout Plain Layout
10121 else output_chunk_names();
10129 \begin_layout Standard
10130 We also have some other output debugging:
10133 \begin_layout Chunk
10137 \begin_layout Standard
10138 \begin_inset listings
10142 \begin_layout Plain Layout
10147 \begin_layout Plain Layout
10149 print "------ chunk names "
10152 \begin_layout Plain Layout
10154 output_chunk_names();
10157 \begin_layout Plain Layout
10159 print "====== chunks"
10162 \begin_layout Plain Layout
10167 \begin_layout Plain Layout
10169 print "++++++ debug"
10172 \begin_layout Plain Layout
10174 for (a in chunks) {
10177 \begin_layout Plain Layout
10179 print a "=" chunks[a];
10182 \begin_layout Plain Layout
10187 \begin_layout Plain Layout
10197 \begin_layout Standard
10198 We do both of these at the end.
10200 \begin_inset Flex CharStyle:Code
10203 \begin_layout Plain Layout
10209 because each chunklet is not necessarily a complete line, and we already
10211 \begin_inset Flex CharStyle:Code
10214 \begin_layout Plain Layout
10220 to each input line in section
10221 \begin_inset CommandInset ref
10223 reference "sub:ORS-chunk-text"
10230 \begin_layout Chunk
10234 \begin_layout Standard
10235 \begin_inset listings
10239 \begin_layout Plain Layout
10244 \begin_layout Plain Layout
10248 chunkref{debug-output}>
10251 \begin_layout Plain Layout
10256 \begin_layout Plain Layout
10260 chunkref{generate-output}>
10263 \begin_layout Plain Layout
10273 \begin_layout Standard
10274 We write chunk names like this.
10275 If we seem to be running in notangle compatibility mode, then we enclose
10277 \begin_inset Flex CharStyle:Code
10280 \begin_layout Plain Layout
10286 the same way notangle does:
10289 \begin_layout Chunk
10290 output_chunk_names()
10293 \begin_layout Standard
10294 \begin_inset listings
10298 \begin_layout Plain Layout
10300 function output_chunk_names( c, prefix, suffix)
10303 \begin_layout Plain Layout
10308 \begin_layout Plain Layout
10310 if (notangle_mode) {
10313 \begin_layout Plain Layout
10318 \begin_layout Plain Layout
10323 \begin_layout Plain Layout
10328 \begin_layout Plain Layout
10330 for (c in chunk_names) {
10333 \begin_layout Plain Layout
10335 print prefix c suffix "
10340 \begin_layout Plain Layout
10345 \begin_layout Plain Layout
10355 \begin_layout Standard
10356 This function would write out all chunks
10359 \begin_layout Chunk
10363 \begin_layout Standard
10364 \begin_inset listings
10368 \begin_layout Plain Layout
10370 function output_chunks( a)
10373 \begin_layout Plain Layout
10378 \begin_layout Plain Layout
10380 for (a in chunk_names) {
10383 \begin_layout Plain Layout
10385 output_chunk(chunk_names[a]);
10388 \begin_layout Plain Layout
10393 \begin_layout Plain Layout
10398 \begin_layout Plain Layout
10402 \begin_layout Plain Layout
10404 function output_chunk(chunk) {
10407 \begin_layout Plain Layout
10412 \begin_layout Plain Layout
10414 lineno_needed = linenos;
10417 \begin_layout Plain Layout
10421 \begin_layout Plain Layout
10423 write_chunk(chunk);
10426 \begin_layout Plain Layout
10431 \begin_layout Plain Layout
10440 \begin_layout Section
10441 Assembling the chunks
10444 \begin_layout Standard
10445 \begin_inset Flex CharStyle:Code
10448 \begin_layout Plain Layout
10454 holds a string consisting of the names of all the chunks that resulted
10455 in this chunk being output.
10457 \begin_inset Note Note
10460 \begin_layout Plain Layout
10461 Make sure it includes the line numbers too...
10467 It should probably also contain the source line numbers at which each inclusion
10471 \begin_layout Chunk
10475 \begin_layout Standard
10476 We first initialize the mode tracker for this chunk.
10479 \begin_layout Standard
10480 \begin_inset listings
10484 \begin_layout Plain Layout
10486 function write_chunk(chunk_name) {
10489 \begin_layout Plain Layout
10493 chunkref{awk-delete-array}(context)>
10496 \begin_layout Plain Layout
10498 return write_chunk_r(chunk_name, context);
10501 \begin_layout Plain Layout
10511 \begin_layout Chunk
10512 write_chunk(),emph={chunk_path}
10515 \begin_layout Standard
10516 \begin_inset listings
10520 \begin_layout Plain Layout
10522 function write_chunk_r(chunk_name, context, indent, tail,
10525 \begin_layout Plain Layout
10530 \begin_layout Plain Layout
10532 chunk_path, chunk_args,
10535 \begin_layout Plain Layout
10537 s, r, src, new_src,
10540 \begin_layout Plain Layout
10545 \begin_layout Plain Layout
10547 chunk_params, part, max_part, part_line, frag, max_frag, text,
10550 \begin_layout Plain Layout
10552 chunklet, only_part, call_chunk_args)
10555 \begin_layout Plain Layout
10565 \begin_layout Subsection
10566 \begin_inset CommandInset label
10568 name "sub:Chunk-parts"
10575 \begin_layout Standard
10576 As mentioned in section
10577 \begin_inset CommandInset ref
10579 reference "sub:lstlistings-includes"
10583 , a chunk name may contain a part specifier in square brackets, limiting
10584 the parts that should be emitted.
10587 \begin_layout Standard
10588 \begin_inset listings
10592 \begin_layout Plain Layout
10594 if (match(chunk_name, "^(.*)
10602 ]$", chunk_name_parts)) {
10605 \begin_layout Plain Layout
10607 chunk_name = chunk_name_parts[1];
10610 \begin_layout Plain Layout
10612 only_part = chunk_name_parts[2];
10615 \begin_layout Plain Layout
10625 \begin_layout Standard
10626 We then create a mode tracker
10629 \begin_layout Standard
10630 \begin_inset listings
10634 \begin_layout Plain Layout
10638 chunkref{new-mode-tracker}(context, chunks[chunk_name, "language"], "")>
10646 \begin_layout Standard
10648 \begin_inset Flex CharStyle:Code
10651 \begin_layout Plain Layout
10657 the names of the parameters that this chunk accepts, whose values were
10658 (optionally) passed in
10659 \begin_inset Flex CharStyle:Code
10662 \begin_layout Plain Layout
10671 \begin_layout Standard
10672 \begin_inset listings
10676 \begin_layout Plain Layout
10678 split(chunks[chunk_name, "params"], chunk_params, " *; *");
10686 \begin_layout Standard
10687 To assemble a chunk, we write out each part.
10690 \begin_layout Chunk
10694 \begin_layout Standard
10695 \begin_inset listings
10699 \begin_layout Plain Layout
10701 if (! (chunk_name in chunk_names)) {
10704 \begin_layout Plain Layout
10706 error(sprintf(_"The root module <<%s>> was not defined.
10713 \begin_layout Plain Layout
10715 chunk_name, chunk_path));
10718 \begin_layout Plain Layout
10723 \begin_layout Plain Layout
10727 \begin_layout Plain Layout
10729 max_part = chunks[chunk_name, "part"];
10732 \begin_layout Plain Layout
10734 for(part = 1; part <= max_part; part++) {
10737 \begin_layout Plain Layout
10739 if (! only_part || part == only_part) {
10742 \begin_layout Plain Layout
10746 chunkref{write-part}>
10749 \begin_layout Plain Layout
10754 \begin_layout Plain Layout
10759 \begin_layout Plain Layout
10761 if (! finalize_mode_tracker(context)) {
10764 \begin_layout Plain Layout
10766 error(sprintf(_"Module %s did not close context properly.
10770 n", chunk_name, chunk_path));
10773 \begin_layout Plain Layout
10778 \begin_layout Plain Layout
10788 \begin_layout Standard
10789 A part can either be a chunklet of lines, or an include of another chunk.
10792 \begin_layout Standard
10793 Chunks may also have parameters, specified in LaTeX style with braces after
10794 the chunk name --- looking like this in the document:
10795 \begin_inset Flex CharStyle:Code
10798 \begin_layout Plain Layout
10799 chunkname{param1, param2}
10805 Arguments are passed in square brackets:
10806 \begin_inset Flex CharStyle:Code
10809 \begin_layout Plain Layout
10812 chunkref{chunkname}[arg1, arg2]
10820 \begin_layout Standard
10821 Before we process each part, we check that the source position hasn't changed
10822 unexpectedly, so that we can know if we need to output a new file-line
10826 \begin_layout Chunk
10830 \begin_layout Standard
10831 \begin_inset listings
10835 \begin_layout Plain Layout
10839 chunkref{check-source-jump}>
10842 \begin_layout Plain Layout
10846 \begin_layout Plain Layout
10848 chunklet = chunks[chunk_name, "part", part];
10851 \begin_layout Plain Layout
10853 if (chunks[chunk_name, "part", part, "type"] == part_type_chunk) {
10856 \begin_layout Plain Layout
10860 chunkref{write-included-chunk}>
10863 \begin_layout Plain Layout
10865 } else if (chunklet SUBSEP "line" in chunks) {
10868 \begin_layout Plain Layout
10872 chunkref{write-chunklets}>
10875 \begin_layout Plain Layout
10880 \begin_layout Plain Layout
10882 # empty last chunklet
10885 \begin_layout Plain Layout
10895 \begin_layout Standard
10896 To write an included chunk, we must detect any optional chunk arguments
10898 Then we recurse calling
10899 \begin_inset Flex Chunkref
10902 \begin_layout Plain Layout
10911 \begin_layout Chunk
10912 write-included-chunk
10915 \begin_layout Standard
10916 \begin_inset listings
10920 \begin_layout Plain Layout
10922 if (match(chunklet, "^([^
10938 )$", chunklet_parts)) {
10941 \begin_layout Plain Layout
10943 chunklet = chunklet_parts[1];
10946 \begin_layout Plain Layout
10948 parse_chunk_args("c-like", chunklet_parts[2], call_chunk_args, "(");
10951 \begin_layout Plain Layout
10953 for (c in call_chunk_args) {
10956 \begin_layout Plain Layout
10958 call_chunk_args[c] = expand_chunk_args(call_chunk_args[c], chunk_params,
10962 \begin_layout Plain Layout
10967 \begin_layout Plain Layout
10972 \begin_layout Plain Layout
10974 split("", call_chunk_args);
10977 \begin_layout Plain Layout
10982 \begin_layout Plain Layout
10984 # update the transforms arrays
10987 \begin_layout Plain Layout
10989 new_src = mode_escaper(context, s, r, src);
10992 \begin_layout Plain Layout
10994 write_chunk_r(chunklet, context,
10997 \begin_layout Plain Layout
10999 chunks[chunk_name, "part", part, "indent"] indent,
11002 \begin_layout Plain Layout
11004 chunks[chunk_name, "part", part, "tail"],
11007 \begin_layout Plain Layout
11014 \begin_layout Plain Layout
11019 \begin_layout Plain Layout
11029 \begin_layout Standard
11030 Before we output a chunklet of lines, we first emit the file and line number
11031 if we have one, and if it is safe to do so.
11035 \begin_layout Standard
11036 Chunklets are generally broken up by includes, so the start of a chunklet
11037 is a good place to do this.
11038 Then we output each line of the chunklet.
11041 \begin_layout Standard
11042 When it is not safe, such as in the middle of a multi-line macro definition,
11044 \begin_inset Flex CharStyle:Code
11047 \begin_layout Plain Layout
11053 is set to true, and in such a case we note that we want to emit the line
11054 statement when it is next safe.
11057 \begin_layout Chunk
11061 \begin_layout Standard
11062 \begin_inset listings
11066 \begin_layout Plain Layout
11068 max_frag = chunks[chunklet, "line"];
11071 \begin_layout Plain Layout
11073 for(frag = 1; frag <= max_frag; frag++) {
11076 \begin_layout Plain Layout
11080 chunkref{write-file-line}>
11088 \begin_layout Standard
11089 We then extract the chunklet text and expand any arguments.
11092 \begin_layout Standard
11093 \begin_inset listings
11097 \begin_layout Plain Layout
11101 \begin_layout Plain Layout
11103 text = chunks[chunklet, frag];
11106 \begin_layout Plain Layout
11111 \begin_layout Plain Layout
11116 \begin_layout Plain Layout
11118 text = expand_chunk_args(text, chunk_params, chunk_args);
11126 \begin_layout Standard
11127 If the text is a single newline (which we keep separate - see
11128 \begin_inset CommandInset ref
11130 reference "lone-newline"
11134 ) then we increment the line number.
11135 In the case where this is the last line of a chunk and it is not a top-level
11136 chunk we replace the newline with an empty string --- because the chunk
11137 that included this chunk will have the newline at the end of the line that
11138 included this chunk.
11141 \begin_layout Standard
11143 \begin_inset Flex CharStyle:Code
11146 \begin_layout Plain Layout
11152 that we have started a new line, so that indentation can be managed with
11153 the following piece of text.
11156 \begin_layout Standard
11157 \begin_inset listings
11161 \begin_layout Plain Layout
11165 \begin_layout Plain Layout
11172 \begin_layout Plain Layout
11177 \begin_layout Plain Layout
11179 if (part == max_part && frag == max_frag && length(chunk_path)) {
11182 \begin_layout Plain Layout
11187 \begin_layout Plain Layout
11192 \begin_layout Plain Layout
11197 \begin_layout Plain Layout
11202 \begin_layout Plain Layout
11212 \begin_layout Standard
11213 If this text does not represent a newline, but we see that we are the first
11214 piece of text on a newline, then we prefix our text with the current indent.
11216 \begin_inset Flex CharStyle:Code
11219 \begin_layout Plain Layout
11225 is a global output-state variable, but the
11226 \begin_inset Flex CharStyle:Code
11229 \begin_layout Plain Layout
11239 \begin_layout Standard
11240 \begin_inset listings
11244 \begin_layout Plain Layout
11246 } else if (length(text) || length(tail)) {
11249 \begin_layout Plain Layout
11251 if (newline) text = indent text;
11254 \begin_layout Plain Layout
11259 \begin_layout Plain Layout
11264 \begin_layout Plain Layout
11273 \begin_layout Standard
11274 Tail will soon no longer be relevant once mode-detection is in place.
11277 \begin_layout Standard
11278 \begin_inset listings
11282 \begin_layout Plain Layout
11287 \begin_layout Plain Layout
11289 mode_tracker(context, text);
11292 \begin_layout Plain Layout
11294 print transform_escape(s, r, text, src);
11302 \begin_layout Standard
11303 If a line ends in a backslash --- suggesting continuation --- then we supress
11304 outputting file-line as it would probably break the continued lines.
11308 \begin_layout Standard
11309 \begin_inset listings
11313 \begin_layout Plain Layout
11318 \begin_layout Plain Layout
11320 lineno_suppressed = substr(lastline, length(lastline)) == "
11327 \begin_layout Plain Layout
11332 \begin_layout Plain Layout
11342 \begin_layout Standard
11343 Of course there is no point in actually outputting the source filename and
11344 line number (file-line) if they don't say anything new! We only need to
11345 emit them if they aren't what is expected, or if we we not able to emit
11346 one when they had changed.
11349 \begin_layout Chunk
11353 \begin_layout Standard
11354 \begin_inset listings
11358 \begin_layout Plain Layout
11360 if (newline && lineno_needed && ! lineno_suppressed) {
11363 \begin_layout Plain Layout
11365 filename = a_filename;
11368 \begin_layout Plain Layout
11373 \begin_layout Plain Layout
11375 print "#line " lineno "
11384 \begin_layout Plain Layout
11389 \begin_layout Plain Layout
11399 \begin_layout Standard
11400 We check if a new file-line is needed by checking if the source line matches
11401 what we (or a compiler) would expect.
11405 \begin_layout Chunk
11409 \begin_layout Standard
11410 \begin_inset listings
11414 \begin_layout Plain Layout
11416 if (linenos && (chunk_name SUBSEP "part" SUBSEP part SUBSEP "FILENAME" in
11420 \begin_layout Plain Layout
11422 a_filename = chunks[chunk_name, "part", part, "FILENAME"];
11425 \begin_layout Plain Layout
11427 a_lineno = chunks[chunk_name, "part", part, "LINENO"];
11430 \begin_layout Plain Layout
11432 if (a_filename != filename || a_lineno != lineno) {
11435 \begin_layout Plain Layout
11440 \begin_layout Plain Layout
11445 \begin_layout Plain Layout
11455 \begin_layout Chapter
11459 \begin_layout Standard
11460 Awk has pretty limited data structures, so we will use two main hashes.
11461 Uninterrupted sequences of a chunk will be stored in
11462 \begin_inset Flex CharStyle:Code
11465 \begin_layout Plain Layout
11471 and the chunklets used in a chunk will be stored in
11472 \begin_inset Flex CharStyle:Code
11475 \begin_layout Plain Layout
11484 \begin_layout Chunk
11488 \begin_layout Standard
11489 \begin_inset listings
11493 \begin_layout Plain Layout
11498 \begin_layout Plain Layout
11508 \begin_layout Standard
11510 \begin_inset Flex CharStyle:Code
11513 \begin_layout Plain Layout
11519 mentioned are not chunk parameters for parameterized chunks, as mentioned
11521 \begin_inset CommandInset ref
11523 reference "cha:Chunk Arguments"
11527 , but the lstlistings style parameters used in the
11528 \begin_inset Flex CharStyle:Code
11531 \begin_layout Plain Layout
11543 \begin_layout Plain Layout
11545 \begin_inset Flex CharStyle:Code
11548 \begin_layout Plain Layout
11554 parameter is used to hold the parameters for parameterized chunks
11562 \begin_layout Chunk
11563 chunk-storage-functions
11566 \begin_layout Standard
11567 \begin_inset listings
11571 \begin_layout Plain Layout
11573 function new_chunk(chunk_name, params,
11576 \begin_layout Plain Layout
11581 \begin_layout Plain Layout
11586 \begin_layout Plain Layout
11591 \begin_layout Plain Layout
11593 # HACK WHILE WE CHANGE TO ( ) for PARAM CHUNKS
11596 \begin_layout Plain Layout
11606 )$", "", chunk_name);
11609 \begin_layout Plain Layout
11611 if (! (chunk_name in chunk_names)) {
11614 \begin_layout Plain Layout
11616 if (debug) print "New chunk " chunk_name;
11619 \begin_layout Plain Layout
11621 chunk_names[chunk_name];
11624 \begin_layout Plain Layout
11626 for (p in params) {
11629 \begin_layout Plain Layout
11631 chunks[chunk_name, p] = params[p];
11634 \begin_layout Plain Layout
11639 \begin_layout Plain Layout
11641 if ("append" in params) {
11644 \begin_layout Plain Layout
11646 append=params["append"];
11649 \begin_layout Plain Layout
11651 if (! (append in chunk_names)) {
11654 \begin_layout Plain Layout
11656 warning("Chunk " chunk_name " is appended to chunk " append " which
11657 is not defined yet");
11660 \begin_layout Plain Layout
11665 \begin_layout Plain Layout
11670 \begin_layout Plain Layout
11672 chunk_include(append, chunk_name);
11675 \begin_layout Plain Layout
11677 chunk_line(append, ORS);
11680 \begin_layout Plain Layout
11685 \begin_layout Plain Layout
11690 \begin_layout Plain Layout
11692 active_chunk = chunk_name;
11695 \begin_layout Plain Layout
11697 prime_chunk(chunk_name);
11700 \begin_layout Plain Layout
11710 \begin_layout Standard
11711 \begin_inset listings
11715 \begin_layout Plain Layout
11719 \begin_layout Plain Layout
11721 function prime_chunk(chunk_name)
11724 \begin_layout Plain Layout
11729 \begin_layout Plain Layout
11731 chunks[chunk_name, "part", ++chunks[chunk_name, "part"] ] =
11736 \begin_layout Plain Layout
11738 chunk_name SUBSEP "chunklet" SUBSEP "" ++chunks[chunk_name, "chunklet"]
11742 \begin_layout Plain Layout
11744 chunks[chunk_name, "part", chunks[chunk_name, "part"], "FILENAME"] = FILENAME;
11747 \begin_layout Plain Layout
11749 chunks[chunk_name, "part", chunks[chunk_name, "part"], "LINENO"] = FNR
11753 \begin_layout Plain Layout
11758 \begin_layout Plain Layout
11762 \begin_layout Plain Layout
11764 function chunk_line(chunk_name, line){
11767 \begin_layout Plain Layout
11769 chunks[chunk_name, "chunklet", chunks[chunk_name, "chunklet"],
11772 \begin_layout Plain Layout
11774 ++chunks[chunk_name, "chunklet", chunks[chunk_name, "chunklet"],
11778 \begin_layout Plain Layout
11783 \begin_layout Plain Layout
11792 \begin_layout Standard
11793 Chunk include represents a
11797 statement, and stores the requirement to include another chunk.
11798 The parameter indent represents the quanity of literal text characters
11803 statement and therefore by how much additional lines of the included chunk
11804 should be indented.
11807 \begin_layout Standard
11808 \begin_inset listings
11812 \begin_layout Plain Layout
11814 function chunk_include(chunk_name, chunk_ref, indent, tail)
11817 \begin_layout Plain Layout
11822 \begin_layout Plain Layout
11824 chunks[chunk_name, "part", ++chunks[chunk_name, "part"] ] = chunk_ref;
11827 \begin_layout Plain Layout
11829 chunks[chunk_name, "part", chunks[chunk_name, "part"], "type" ] = part_type_ch
11833 \begin_layout Plain Layout
11835 chunks[chunk_name, "part", chunks[chunk_name, "part"], "indent" ] = indent_str
11839 \begin_layout Plain Layout
11841 chunks[chunk_name, "part", chunks[chunk_name, "part"], "tail" ] = tail;
11844 \begin_layout Plain Layout
11846 prime_chunk(chunk_name);
11849 \begin_layout Plain Layout
11854 \begin_layout Plain Layout
11863 \begin_layout Standard
11864 The indent is calculated by indent_string, which may in future convert some
11865 spaces into tab characters.
11866 This function works by generating a printf padded format string, like
11867 \begin_inset Flex CharStyle:Code
11870 \begin_layout Plain Layout
11876 for an indent of 22, and then printing an empty string using that format.
11879 \begin_layout Standard
11880 \begin_inset listings
11884 \begin_layout Plain Layout
11886 function indent_string(indent) {
11889 \begin_layout Plain Layout
11891 return sprintf("%" indent "s", "");
11894 \begin_layout Plain Layout
11904 \begin_layout Chapter
11905 \begin_inset CommandInset label
11914 \begin_layout Standard
11915 I use Arnold Robbins public domain getopt (1993 revision).
11916 This is probably the same one that is covered in chapter 12 of
11917 \begin_inset Quotes eld
11920 Edition 3 of GAWK: Effective AWK Programming: A User's Guide for GNU Awk
11921 \begin_inset Quotes erd
11924 but as that is licensed under the GNU Free Documentation License, Version
11925 1.3, which conflicts with the GPL3, I can't use it from there (or it's accompany
11926 ing explanations), so I do my best to explain how it works here.
11929 \begin_layout Standard
11930 The getopt.awk header is:
11933 \begin_layout Chunk
11934 getopt.awk-header,language=awk,morestring=[b]{/},morekeywords=else
11937 \begin_layout Standard
11938 \begin_inset listings
11942 \begin_layout Plain Layout
11944 # getopt.awk --- do C library getopt(3) function in awk
11947 \begin_layout Plain Layout
11952 \begin_layout Plain Layout
11954 # Arnold Robbins, arnold@skeeve.com, Public Domain
11957 \begin_layout Plain Layout
11962 \begin_layout Plain Layout
11964 # Initial version: March, 1991
11967 \begin_layout Plain Layout
11969 # Revised: May, 1993
11972 \begin_layout Plain Layout
11981 \begin_layout Standard
11982 The provided explanation is:
11985 \begin_layout Chunk
11989 \begin_layout Standard
11990 \begin_inset listings
11994 \begin_layout Plain Layout
11996 # External variables:
11999 \begin_layout Plain Layout
12001 # Optind -- index in ARGV of first nonoption argument
12004 \begin_layout Plain Layout
12006 # Optarg -- string value of argument to current option
12009 \begin_layout Plain Layout
12011 # Opterr -- if nonzero, print our own diagnostic
12014 \begin_layout Plain Layout
12016 # Optopt -- current option letter
12019 \begin_layout Plain Layout
12023 \begin_layout Plain Layout
12028 \begin_layout Plain Layout
12030 # -1 at end of options
12033 \begin_layout Plain Layout
12035 # ? for unrecognized option
12038 \begin_layout Plain Layout
12040 # <c> a character representing the current option
12043 \begin_layout Plain Layout
12047 \begin_layout Plain Layout
12052 \begin_layout Plain Layout
12054 # _opti -- index in multi-flag option, e.g., -abc
12057 \begin_layout Plain Layout
12066 \begin_layout Standard
12067 The function follows.
12068 The final two parameters,
12069 \begin_inset Flex CharStyle:Code
12072 \begin_layout Plain Layout
12079 \begin_inset Flex CharStyle:Code
12082 \begin_layout Plain Layout
12088 are local variables and not parameters --- as indicated by the multiple
12089 spaces preceding them.
12090 Awk doesn't care, the multiple spaces are a convention to help us humans.
12093 \begin_layout Chunk
12094 getopt.awk-getopt()
12097 \begin_layout Standard
12098 \begin_inset listings
12102 \begin_layout Plain Layout
12104 function getopt(argc, argv, options, thisopt, i)
12107 \begin_layout Plain Layout
12112 \begin_layout Plain Layout
12114 if (length(options) == 0) # no options given
12117 \begin_layout Plain Layout
12122 \begin_layout Plain Layout
12124 if (argv[Optind] == "--") { # all done
12127 \begin_layout Plain Layout
12132 \begin_layout Plain Layout
12137 \begin_layout Plain Layout
12142 \begin_layout Plain Layout
12144 } else if (argv[Optind] !~ /^-[^:
12159 \begin_layout Plain Layout
12164 \begin_layout Plain Layout
12169 \begin_layout Plain Layout
12174 \begin_layout Plain Layout
12179 \begin_layout Plain Layout
12184 \begin_layout Plain Layout
12186 thisopt = substr(argv[Optind], _opti, 1)
12189 \begin_layout Plain Layout
12194 \begin_layout Plain Layout
12196 i = index(options, thisopt)
12199 \begin_layout Plain Layout
12204 \begin_layout Plain Layout
12209 \begin_layout Plain Layout
12211 printf("%c -- invalid option
12216 \begin_layout Plain Layout
12218 thisopt) > "/dev/stderr"
12221 \begin_layout Plain Layout
12223 if (_opti >= length(argv[Optind])) {
12226 \begin_layout Plain Layout
12231 \begin_layout Plain Layout
12236 \begin_layout Plain Layout
12241 \begin_layout Plain Layout
12246 \begin_layout Plain Layout
12251 \begin_layout Plain Layout
12261 \begin_layout Standard
12262 At this point, the option has been found and we need to know if it takes
12266 \begin_layout Standard
12267 \begin_inset listings
12271 \begin_layout Plain Layout
12273 if (substr(options, i + 1, 1) == ":") {
12276 \begin_layout Plain Layout
12278 # get option argument
12281 \begin_layout Plain Layout
12283 if (length(substr(argv[Optind], _opti + 1)) > 0)
12286 \begin_layout Plain Layout
12288 Optarg = substr(argv[Optind], _opti + 1)
12291 \begin_layout Plain Layout
12296 \begin_layout Plain Layout
12298 Optarg = argv[++Optind]
12301 \begin_layout Plain Layout
12306 \begin_layout Plain Layout
12311 \begin_layout Plain Layout
12316 \begin_layout Plain Layout
12318 if (_opti == 0 || _opti >= length(argv[Optind])) {
12321 \begin_layout Plain Layout
12326 \begin_layout Plain Layout
12331 \begin_layout Plain Layout
12336 \begin_layout Plain Layout
12341 \begin_layout Plain Layout
12346 \begin_layout Plain Layout
12353 A test program is built in, too
12356 \begin_layout Chunk
12360 \begin_layout Standard
12361 \begin_inset listings
12365 \begin_layout Plain Layout
12370 \begin_layout Plain Layout
12372 Opterr = 1 # default is to diagnose
12375 \begin_layout Plain Layout
12377 Optind = 1 # skip ARGV[0]
12380 \begin_layout Plain Layout
12385 \begin_layout Plain Layout
12387 if (_getopt_test) {
12390 \begin_layout Plain Layout
12392 while ((_go_c = getopt(ARGC, ARGV, "ab:cd")) != -1)
12395 \begin_layout Plain Layout
12397 printf("c = <%c>, optarg = <%s>
12402 \begin_layout Plain Layout
12407 \begin_layout Plain Layout
12409 printf("non-option arguments:
12414 \begin_layout Plain Layout
12416 for (; Optind < ARGC; Optind++)
12419 \begin_layout Plain Layout
12428 \begin_layout Plain Layout
12430 Optind, ARGV[Optind])
12433 \begin_layout Plain Layout
12438 \begin_layout Plain Layout
12448 \begin_layout Standard
12449 The entire getopt.awk is made out of these chunks in order
12452 \begin_layout Chunk
12456 \begin_layout Standard
12457 \begin_inset listings
12461 \begin_layout Plain Layout
12465 chunkref{getopt.awk-header}>
12468 \begin_layout Plain Layout
12472 \begin_layout Plain Layout
12476 chunkref{getopt.awk-notes}>
12479 \begin_layout Plain Layout
12483 chunkref{getopt.awk-getopt()}>
12486 \begin_layout Plain Layout
12490 chunkref{getopt.awk-begin}>
12498 \begin_layout Standard
12499 Although we only want the header and function:
12502 \begin_layout Chunk
12506 \begin_layout Standard
12507 \begin_inset listings
12511 \begin_layout Plain Layout
12513 # try: locate getopt.awk for the full original file
12516 \begin_layout Plain Layout
12518 # as part of your standard awk installation
12521 \begin_layout Plain Layout
12525 chunkref{getopt.awk-header}>
12528 \begin_layout Plain Layout
12532 \begin_layout Plain Layout
12536 chunkref{getopt.awk-getopt()}>
12544 \begin_layout Chapter
12545 Newfangle LaTeX source code
12548 \begin_layout Section
12552 \begin_layout Standard
12553 Here we define a Lyx .module file that makes it convenient to use LyX for
12554 writing such literate programs.
12557 \begin_layout Standard
12559 \begin_inset Flex CharStyle:Code
12562 \begin_layout Plain Layout
12568 can be installed in your personal
12569 \begin_inset Flex CharStyle:Code
12572 \begin_layout Plain Layout
12573 .lyx/layouts folder
12579 You will need to Tools Reconfigure so that LyX notices it.
12580 It adds a new format Chunk, which should precede every listing and contain
12585 \begin_layout Chunk
12586 ./newfangle.module,language=
12589 \begin_layout Standard
12590 \begin_inset listings
12594 \begin_layout Plain Layout
12598 DeclareLyXModule{Newfangle Literate Listings}
12601 \begin_layout Plain Layout
12606 \begin_layout Plain Layout
12608 # Newfangle literate listings allow one to write
12611 \begin_layout Plain Layout
12613 # literate programs after the fashion of noweb, but without having
12616 \begin_layout Plain Layout
12618 # to use noweave to generate the documentation.
12619 Instead the listings
12622 \begin_layout Plain Layout
12624 # package is extended in conjunction with the noweb package to implement
12627 \begin_layout Plain Layout
12629 # to code formating directly as latex.
12632 \begin_layout Plain Layout
12634 # The newfangle awk script
12637 \begin_layout Plain Layout
12642 \begin_layout Plain Layout
12646 \begin_layout Plain Layout
12651 \begin_layout Plain Layout
12655 \begin_layout Plain Layout
12660 \begin_layout Plain Layout
12664 chunkref{./newfangle.sty}>
12667 \begin_layout Plain Layout
12672 \begin_layout Plain Layout
12676 \begin_layout Plain Layout
12680 chunkref{chunkstyle}>
12683 \begin_layout Plain Layout
12687 \begin_layout Plain Layout
12691 chunkref{chunkref}>
12699 \begin_layout Subsection
12703 \begin_layout Standard
12708 style is to make it easier for LyX users to provide the name to
12709 \begin_inset Flex CharStyle:Code
12712 \begin_layout Plain Layout
12721 Normally this requires right-clicking on the listing, choosing settings,
12722 advanced, and then typing
12723 \begin_inset Flex CharStyle:Code
12726 \begin_layout Plain Layout
12733 This has the further disadvantage that the name (and other options) are
12734 not generally visible during document editing.
12737 \begin_layout Standard
12738 The chunk style is defined as a LaTeX command, so that all text on the same
12739 line is passed to the LaTeX command
12740 \begin_inset Flex CharStyle:Code
12743 \begin_layout Plain Layout
12750 This makes it easy to parse using
12751 \begin_inset Flex CharStyle:Code
12754 \begin_layout Plain Layout
12760 , and easy to pass these options on to the listings package.
12761 The first word in a chunk section should be the chunk name, and will have
12763 \begin_inset Flex CharStyle:Code
12766 \begin_layout Plain Layout
12773 Any other words are accepted arguments to
12774 \begin_inset Flex CharStyle:Code
12777 \begin_layout Plain Layout
12788 \begin_layout Standard
12789 We set PassThru to 1 because the user is actually entering raw latex.
12792 \begin_layout Chunk
12796 \begin_layout Standard
12797 \begin_inset listings
12801 \begin_layout Plain Layout
12806 \begin_layout Plain Layout
12811 \begin_layout Plain Layout
12816 \begin_layout Plain Layout
12818 Margin First_Dynamic
12821 \begin_layout Plain Layout
12823 LeftMargin Chunk:xxx
12826 \begin_layout Plain Layout
12831 \begin_layout Plain Layout
12836 \begin_layout Plain Layout
12838 LabelString "Chunk:"
12841 \begin_layout Plain Layout
12846 \begin_layout Plain Layout
12851 \begin_layout Plain Layout
12860 \begin_layout Standard
12861 To make the label very visible we choose a larger font coloured red.
12864 \begin_layout Standard
12865 \begin_inset listings
12869 \begin_layout Plain Layout
12874 \begin_layout Plain Layout
12879 \begin_layout Plain Layout
12884 \begin_layout Plain Layout
12889 \begin_layout Plain Layout
12894 \begin_layout Plain Layout
12899 \begin_layout Plain Layout
12904 \begin_layout Plain Layout
12914 \begin_layout Subsection
12918 \begin_layout Standard
12919 We also define the Chunkref style which can be used to express cross references
12923 \begin_layout Chunk
12927 \begin_layout Standard
12928 \begin_inset listings
12932 \begin_layout Plain Layout
12934 InsetLayout Chunkref
12937 \begin_layout Plain Layout
12942 \begin_layout Plain Layout
12947 \begin_layout Plain Layout
12952 \begin_layout Plain Layout
12957 \begin_layout Plain Layout
12962 \begin_layout Plain Layout
12967 \begin_layout Plain Layout
12972 \begin_layout Plain Layout
12977 \begin_layout Plain Layout
12987 \begin_layout Section
12988 \begin_inset CommandInset label
12990 name "sec:Latex-Macros"
12997 \begin_layout Standard
13011 As noweb defines it's own
13012 \begin_inset Flex CharStyle:Code
13015 \begin_layout Plain Layout
13023 environment, we re-define the one that LyX logical markup module expects
13027 \begin_layout Chunk
13028 ./newfangle.sty,language=tex,basicstyle=
13033 \begin_layout Standard
13034 \begin_inset listings
13038 \begin_layout Plain Layout
13042 usepackage{listings}%
13045 \begin_layout Plain Layout
13052 \begin_layout Plain Layout
13059 \begin_layout Plain Layout
13075 \begin_layout Standard
13077 \begin_inset Flex CharStyle:Code
13080 \begin_layout Plain Layout
13087 \begin_inset Flex CharStyle:Code
13090 \begin_layout Plain Layout
13098 which will need renaming to
13099 \begin_inset Flex CharStyle:Code
13102 \begin_layout Plain Layout
13110 when I can do this without clashing with
13111 \begin_inset Flex CharStyle:Code
13114 \begin_layout Plain Layout
13125 \begin_layout Standard
13126 \begin_inset listings
13130 \begin_layout Plain Layout
13134 lstnewenvironment{Chunk}{
13146 \begin_layout Standard
13147 We also define a suitable
13148 \begin_inset Flex CharStyle:Code
13151 \begin_layout Plain Layout
13159 of parameters that suit the literate programming style after the fashion
13167 \begin_layout Standard
13168 \begin_inset listings
13172 \begin_layout Plain Layout
13176 lstset{numbers=left, stepnumber=5, numbersep=5pt,
13179 \begin_layout Plain Layout
13181 breaklines=false,basicstyle=
13186 \begin_layout Plain Layout
13198 \begin_layout Standard
13199 We also define a notangle-like mechanism for
13203 to LaTeX from the listing, and by which we can refer to other listings.
13205 \begin_inset Flex CharStyle:Code
13208 \begin_layout Plain Layout
13209 =<\SpecialChar \ldots{}
13215 sequence to contain LaTeX code, and include another like this chunk:
13216 \begin_inset Flex CharStyle:Code
13219 \begin_layout Plain Layout
13222 chunkref{chunkname}>
13229 \begin_inset Flex CharStyle:Code
13232 \begin_layout Plain Layout
13233 =<\SpecialChar \ldots{}
13239 is already defined to contain LaTeX code for this document --- this is
13244 document after all --- the code fragment below effectively contains the
13246 \begin_inset Flex CharStyle:Code
13249 \begin_layout Plain Layout
13256 To avoid problems with document generation, I had to declare an lstlistings
13258 \begin_inset Flex CharStyle:Code
13261 \begin_layout Plain Layout
13267 for this listing only; which in LyX was done by right-clicking the listings
13269 \begin_inset Flex CharStyle:Code
13272 \begin_layout Plain Layout
13278 \SpecialChar \menuseparator
13280 \begin_inset Flex CharStyle:Code
13283 \begin_layout Plain Layout
13292 \begin_layout Standard
13293 \begin_inset Note Note
13296 \begin_layout Plain Layout
13297 =< isn't enjoyed literally here, in a listing when the escape sequence is
13298 already defined as shown...
13299 we need to somehow escape this representation...
13307 \begin_layout Standard
13308 \begin_inset listings
13309 lstparams "escapeinside={}"
13313 \begin_layout Plain Layout
13317 lstset{escapeinside={=<}{>}}%
13325 \begin_layout Standard
13326 Although our macros will contain the @ symbol, they will be included in
13328 \begin_inset Flex CharStyle:Code
13331 \begin_layout Plain Layout
13339 section by LyX; however we keep the commented out
13340 \begin_inset Flex CharStyle:Code
13343 \begin_layout Plain Layout
13352 The listings package likes to centre the titles, but noweb titles are specially
13353 formatted and must be left aligned.
13354 The simplest way to do this turned out to be by removing the definition
13356 \begin_inset Flex CharStyle:Code
13359 \begin_layout Plain Layout
13368 This may interact badly if other listings want a regular title or caption.
13369 We remember the old maketitle in case we need it.
13372 \begin_layout Standard
13373 \begin_inset listings
13377 \begin_layout Plain Layout
13384 \begin_layout Plain Layout
13386 %somehow re-defining maketitle gives us a left-aligned title
13389 \begin_layout Plain Layout
13391 %which is extactly what our specially formatted title needs!
13394 \begin_layout Plain Layout
13402 newfangle@lst@maketitle
13407 \begin_layout Plain Layout
13423 \begin_layout Subsection
13424 \begin_inset CommandInset label
13426 name "sub:The-chunk-command"
13433 \begin_layout Standard
13434 Our chunk command accepts one argument, and calls
13435 \begin_inset Flex CharStyle:Code
13438 \begin_layout Plain Layout
13448 \begin_inset Flex CharStyle:Code
13451 \begin_layout Plain Layout
13459 will note the name, this is erased when the next
13460 \begin_inset Flex CharStyle:Code
13463 \begin_layout Plain Layout
13471 starts, so we make a note of this in
13472 \begin_inset Flex CharStyle:Code
13475 \begin_layout Plain Layout
13483 and restore in in lstlistings Init hook.
13486 \begin_layout Standard
13487 \begin_inset listings
13491 \begin_layout Plain Layout
13500 \begin_layout Plain Layout
13506 newfanglecaption},name=#1}%
13509 \begin_layout Plain Layout
13522 \begin_layout Plain Layout
13527 \begin_layout Plain Layout
13543 \begin_layout Subsubsection
13547 \begin_layout Standard
13548 Newfangle permits parameterized chunks, and requires the paramters to be
13549 specified as listings options.
13550 The newfangle script uses this, and although we don't do anything with
13551 these in the LaTeX code right now, we need to stop the listings package
13555 \begin_layout Standard
13556 \begin_inset listings
13560 \begin_layout Plain Layout
13570 newfangle@chunk@params{#1}}%
13578 \begin_layout Standard
13579 As it is common to define a chunk which then needs appending to another
13580 chunk, and annoying to have to declare a single line chunk to manage the
13581 include, we support an
13582 \begin_inset Flex CharStyle:Code
13585 \begin_layout Plain Layout
13595 \begin_layout Standard
13596 \begin_inset listings
13600 \begin_layout Plain Layout
13610 newfangle@chunk@append{#1}}%
13618 \begin_layout Subsection
13619 The noweb styled caption
13622 \begin_layout Standard
13623 We define a public macro
13624 \begin_inset Flex CharStyle:Code
13627 \begin_layout Plain Layout
13635 which can be set as a regular title.
13637 \begin_inset Flex CharStyle:Code
13640 \begin_layout Plain Layout
13649 \begin_inset Flex CharStyle:Code
13652 \begin_layout Plain Layout
13660 at the appriate time when the caption is emitted.
13663 \begin_layout Standard
13664 \begin_inset listings
13668 \begin_layout Plain Layout
13678 newfangle@caption}%
13686 \begin_layout Standard
13687 \begin_inset Float figure
13693 \begin_layout Plain Layout
13694 \begin_inset Box Boxed
13703 height_special "totalheight"
13706 \begin_layout Plain Layout
13708 \begin_inset space \qquad{}
13716 \begin_inset Formula $\equiv+$
13720 \begin_inset space \qquad{}
13724 \begin_inset space \qquad{}
13728 \begin_inset space \qquad{}
13732 \begin_inset Formula $\triangleleft$
13736 \begin_inset space \quad{}
13740 \begin_inset Formula $\triangleright$
13746 \begin_layout Plain Layout
13749 In this example, the current chunk is 22c, and therefore the third chunk
13753 \begin_layout Plain Layout
13764 \begin_layout Plain Layout
13767 The first chunk with this name (19b) occurs as the second chunk on page
13771 \begin_layout Plain Layout
13774 The previous chunk (22d) with the same name is the second chunk on page
13778 \begin_layout Plain Layout
13781 The next chunk (24d) is the fourth chunk on page 24.
13784 \begin_layout Plain Layout
13785 \begin_inset Caption
13787 \begin_layout Plain Layout
13803 The general noweb output format compactly identifies the current chunk,
13804 and references to the first chunk, and the previous and next chunks that
13805 have the same name.
13809 \begin_layout Standard
13810 This means that we need to keep a counter for each chunk-name, that we use
13811 to count chunks of the same name.
13815 \begin_layout Subsection
13819 \begin_layout Standard
13820 It would be natural to have a counter for each chunk name, but TeX would
13821 soon run out of counters
13825 \begin_layout Plain Layout
13826 \SpecialChar \ldots{}
13831 run out of counters and so I had to re-write the LaTeX macros to share
13832 a counter as described here
13837 , so we have one counter which we save at the end of a chunk and restore
13838 at the beginning of a chunk.
13841 \begin_layout Standard
13842 \begin_inset listings
13846 \begin_layout Plain Layout
13850 newcounter{newfangle@chunkcounter}%
13858 \begin_layout Standard
13859 We construct the name of this variable to store the counter to be the text
13861 \begin_inset Flex CharStyle:Code
13864 \begin_layout Plain Layout
13870 prefixed onto the chunks own name, and store it in
13871 \begin_inset Flex CharStyle:Code
13874 \begin_layout Plain Layout
13886 \begin_layout Standard
13887 We save the counter like this:
13890 \begin_layout Chunk
13894 \begin_layout Standard
13895 \begin_inset listings
13899 \begin_layout Plain Layout
13915 arabic{newfangle@chunkcounter}}%
13923 \begin_layout Standard
13924 and restore the counter like this:
13927 \begin_layout Chunk
13931 \begin_layout Standard
13932 \begin_inset listings
13936 \begin_layout Plain Layout
13940 setcounter{newfangle@chunkcounter}{
13954 \begin_layout Chunk
13958 \begin_layout Standard
13959 If there does not already exist a variable whose name is stored in
13960 \begin_inset Flex CharStyle:Code
13963 \begin_layout Plain Layout
13971 , then we know we are the first chunk with this name, and then define a
13976 \begin_layout Standard
13977 Although chunks of the same name share a common counter, they must still
13979 We use is the internal name of the listing, suffixed by the counter value.
13980 So the first chunk might be
13981 \begin_inset Flex CharStyle:Code
13984 \begin_layout Plain Layout
13990 and the second chunk be
13991 \begin_inset Flex CharStyle:Code
13994 \begin_layout Plain Layout
14003 \begin_layout Standard
14004 We also calculate the name of the previous chunk if we can (before we increment
14005 the chunk counter).
14006 If this is the first chunk of that name, then
14007 \begin_inset Flex CharStyle:Code
14010 \begin_layout Plain Layout
14019 \begin_inset Flex CharStyle:Code
14022 \begin_layout Plain Layout
14030 which the noweb package will interpret as not existing.
14033 \begin_layout Standard
14034 \begin_inset listings
14038 \begin_layout Plain Layout
14044 newfangle@caption{%
14047 \begin_layout Plain Layout
14053 chunkcount{lst-chunk-
14058 \begin_layout Plain Layout
14067 \begin_layout Plain Layout
14082 \begin_layout Plain Layout
14086 setcounter{newfangle@chunkcounter}{
14095 \begin_layout Plain Layout
14106 \begin_layout Plain Layout
14111 \begin_layout Plain Layout
14115 setcounter{newfangle@chunkcounter}{
14124 \begin_layout Plain Layout
14134 arabic{newfangle@chunkcounter}}%
14137 \begin_layout Plain Layout
14147 \begin_layout Standard
14148 After incrementing the chunk counter, we then define the name of this chunk,
14149 as well as the name of the first chunk.
14152 \begin_layout Standard
14153 \begin_inset listings
14157 \begin_layout Plain Layout
14161 addtocounter{newfangle@chunkcounter}{1}%
14164 \begin_layout Plain Layout
14180 arabic{newfangle@chunkcounter}}%
14183 \begin_layout Plain Layout
14193 arabic{newfangle@chunkcounter}}%
14196 \begin_layout Plain Layout
14212 \begin_layout Standard
14213 We now need to calculate the name of the next chunk.
14214 We do this by temporarily skipping the counter on by one; however there
14215 may not actually be another chunk with this name! We detect this by also
14216 defining a label for each chunk based on the chunkname.
14217 If there is a next chunkname then it will define a label with that name.
14218 As labels are persistent, we can at least tell the second time LaTeX is
14220 If we don't find such a defined label then we define
14221 \begin_inset Flex CharStyle:Code
14224 \begin_layout Plain Layout
14233 \begin_inset Flex CharStyle:Code
14236 \begin_layout Plain Layout
14247 \begin_layout Standard
14248 \begin_inset listings
14252 \begin_layout Plain Layout
14256 addtocounter{newfangle@chunkcounter}{1}%
14259 \begin_layout Plain Layout
14269 arabic{newfangle@chunkcounter}}%
14272 \begin_layout Plain Layout
14276 @ifundefined{r@label-
14292 \begin_layout Standard
14293 The noweb package requires that we define a
14294 \begin_inset Flex CharStyle:Code
14297 \begin_layout Plain Layout
14305 for every chunk, with a unique name, which is then used to print out it's
14309 \begin_layout Standard
14310 We also define a regular label for this chunk, as was mentioned above when
14312 \begin_inset Flex CharStyle:Code
14315 \begin_layout Plain Layout
14324 This requires LaTeX to be run at least twice after new chunk sections are
14325 added --- but noweb requried that anyway.
14328 \begin_layout Standard
14329 \begin_inset listings
14333 \begin_layout Plain Layout
14342 \begin_layout Plain Layout
14344 % define this label for every chunk instance, so we
14347 \begin_layout Plain Layout
14349 % can tell when we are the last chunk of this name
14352 \begin_layout Plain Layout
14366 \begin_layout Standard
14367 We also try and add the chunk to the list of listings, but I'm afraid we
14368 don't do very well.
14369 We want each chunk name listing once, with all of it's references.
14372 \begin_layout Standard
14373 \begin_inset listings
14377 \begin_layout Plain Layout
14381 addcontentsline{lol}{lstlisting}{
14397 \begin_layout Standard
14398 We then call the noweb output macros in the same way that noweave generates
14399 them, except that we don't need to call
14400 \begin_inset Flex CharStyle:Code
14403 \begin_layout Plain Layout
14406 nwstartdeflinemarkup
14412 \begin_inset Flex CharStyle:Code
14415 \begin_layout Plain Layout
14423 -- and if we do it messes up the output somewhat.
14426 \begin_layout Standard
14427 \begin_inset listings
14431 \begin_layout Plain Layout
14438 \begin_layout Plain Layout
14443 \begin_layout Plain Layout
14450 \begin_layout Plain Layout
14459 \begin_layout Plain Layout
14464 \begin_layout Plain Layout
14469 \begin_layout Plain Layout
14474 \begin_layout Plain Layout
14481 \begin_layout Plain Layout
14488 \begin_layout Plain Layout
14493 \begin_layout Plain Layout
14502 \begin_layout Plain Layout
14506 @ifundefined{newfangle@chunk@params}{}{%
14509 \begin_layout Plain Layout
14513 newfangle@chunk@params)%
14516 \begin_layout Plain Layout
14521 \begin_layout Plain Layout
14532 \begin_layout Plain Layout
14541 \begin_layout Plain Layout
14546 \begin_layout Plain Layout
14550 @ifundefined{newfangle@chunk@append}{}{%
14553 \begin_layout Plain Layout
14559 newfangle@chunk@append{x}
14564 \begin_layout Plain Layout
14568 newfangle@chunk@append%
14571 \begin_layout Plain Layout
14578 \begin_layout Plain Layout
14583 \begin_layout Plain Layout
14591 newfangle@chunk@append{}%
14594 \begin_layout Plain Layout
14601 \begin_layout Plain Layout
14606 \begin_layout Plain Layout
14611 \begin_layout Plain Layout
14630 \begin_layout Plain Layout
14634 nwstartdeflinemarkup%
14637 \begin_layout Plain Layout
14648 \begin_layout Plain Layout
14652 nwenddeflinemarkup%
14655 \begin_layout Plain Layout
14665 \begin_layout Standard
14666 Originally this was developed as a
14667 \begin_inset Flex CharStyle:Code
14670 \begin_layout Plain Layout
14676 aspect, in the Init hook, but it was found easier to affect the title without
14678 \begin_inset Flex CharStyle:Code
14681 \begin_layout Plain Layout
14684 lst@AddToHookExe{PreSet}
14689 is still required to set the listings name to the name passed to the
14690 \begin_inset Flex CharStyle:Code
14693 \begin_layout Plain Layout
14704 \begin_layout Standard
14705 \begin_inset listings
14709 \begin_layout Plain Layout
14713 lst@BeginAspect{newfangle}
14716 \begin_layout Plain Layout
14720 lst@Key{newfangle}{true}[t]{
14722 lstKV@SetIf{#1}{true}}
14725 \begin_layout Plain Layout
14729 lst@AddToHookExe{PreSet}{
14740 \begin_layout Plain Layout
14744 lst@AddToHook{Init}{}%
14749 \begin_layout Plain Layout
14761 \begin_layout Subsection
14765 \begin_layout Standard
14768 chunkref command which makes it easy to generate visual references to different
14772 \begin_layout Standard
14773 \begin_inset Tabular
14774 <lyxtabular version="3" rows="4" columns="2">
14776 <column alignment="center" valignment="top" width="0">
14777 <column alignment="center" valignment="top" width="0">
14779 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
14782 \begin_layout Plain Layout
14788 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
14791 \begin_layout Plain Layout
14799 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
14802 \begin_layout Plain Layout
14810 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
14813 \begin_layout Plain Layout
14817 \begin_layout Plain Layout
14833 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
14836 \begin_layout Plain Layout
14839 chunkref[3]{preamble}
14844 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
14847 \begin_layout Plain Layout
14851 \begin_layout Plain Layout
14855 chunkref[3]{preamble}
14867 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
14870 \begin_layout Plain Layout
14873 chunkref{preamble}[arg1, arg2]
14878 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
14881 \begin_layout Plain Layout
14885 \begin_layout Plain Layout
14889 chunkref{preamble}[arg1, arg2]
14907 \begin_layout Standard
14908 Chunkref can also be used within a code chunk to include another code chunk.
14909 The third optional parameter to chunkref is a comma sepatarated list of
14910 arguments, which will replace defined parameters in the chunkref.
14911 \begin_inset Note Note
14914 \begin_layout Plain Layout
14915 Darn it, if I have: =<
14917 chunkref{new-mode-tracker}[{chunks[chunk_name, "language"]},{mode}]> the
14918 inner braces (inside [ ]) cause _ to signify subscript even though we have
14927 \begin_layout Standard
14928 \begin_inset listings
14932 \begin_layout Plain Layout
14941 \begin_layout Plain Layout
14950 \begin_layout Plain Layout
14961 \begin_layout Plain Layout
14968 \begin_layout Plain Layout
14979 \begin_layout Plain Layout
14984 \begin_layout Plain Layout
14993 \begin_layout Plain Layout
14999 chunkref@i{#1}{#2}}{
15001 chunkref@i{#1}{#2}()}%
15004 \begin_layout Plain Layout
15009 \begin_layout Plain Layout
15015 chunkref@i#1#2(#3){%
15018 \begin_layout Plain Layout
15027 \begin_layout Plain Layout
15036 \begin_layout Plain Layout
15045 \begin_layout Plain Layout
15054 \begin_layout Plain Layout
15065 \begin_layout Plain Layout
15074 \begin_layout Plain Layout
15081 \begin_layout Plain Layout
15092 \begin_layout Plain Layout
15099 \begin_layout Plain Layout
15110 \begin_layout Plain Layout
15121 \begin_layout Plain Layout
15130 \begin_layout Plain Layout
15137 \begin_layout Plain Layout
15142 \begin_layout Plain Layout
15151 \begin_layout Plain Layout
15162 \begin_layout Plain Layout
15169 \begin_layout Plain Layout
15176 \begin_layout Plain Layout
15183 \begin_layout Plain Layout
15194 \begin_layout Plain Layout
15201 \begin_layout Plain Layout
15205 chunkref@args #3,)%
15208 \begin_layout Plain Layout
15215 \begin_layout Plain Layout
15224 \begin_layout Plain Layout
15229 \begin_layout Plain Layout
15234 \begin_layout Plain Layout
15243 \begin_layout Plain Layout
15253 \begin_layout Subsection
15257 \begin_layout Standard
15258 \begin_inset listings
15262 \begin_layout Plain Layout
15267 \begin_layout Plain Layout
15279 \begin_layout Chapter
15280 Extracting newfangle
15283 \begin_layout Section
15284 Extracting from Lyx
15287 \begin_layout Standard
15288 To extract from LyX, you will need to configure LyX as explained in section
15290 \begin_inset CommandInset ref
15292 reference "sub:Configuring-the-build"
15299 \begin_layout Standard
15300 \begin_inset CommandInset label
15302 name "lyx-build-script"
15306 And this lyx-build scrap will extract newfangle for me.
15309 \begin_layout Chunk
15310 lyx-build,language=sh
15313 \begin_layout Standard
15314 \begin_inset listings
15318 \begin_layout Plain Layout
15323 \begin_layout Plain Layout
15328 \begin_layout Plain Layout
15332 \begin_layout Plain Layout
15336 chunkref{lyx-build-helper}>
15339 \begin_layout Plain Layout
15341 cd $PROJECT_DIR || exit 1
15344 \begin_layout Plain Layout
15348 \begin_layout Plain Layout
15350 python -m elyxer --css lyx.css $LYX_SRC |
15355 \begin_layout Plain Layout
15357 iconv -c -f utf-8 -t ISO-8859-1//TRANSLIT |
15362 \begin_layout Plain Layout
15370 1>/' > www/docs/newfangle.html
15373 \begin_layout Plain Layout
15375 /usr/local/bin/newfangle -R./newfangle $TEX_SRC > ./newfangle
15378 \begin_layout Plain Layout
15380 /usr/local/bin/newfangle -R./newfangle.module $TEX_SRC > ./newfangle.module
15383 \begin_layout Plain Layout
15387 \begin_layout Plain Layout
15391 chunkref{test:helpers}>
15394 \begin_layout Plain Layout
15396 export NEWFANGLE=./newfangle
15399 \begin_layout Plain Layout
15401 export TMP=${TMP:-/tmp}
15404 \begin_layout Plain Layout
15408 chunkref{test:run-tests}>
15411 \begin_layout Plain Layout
15413 # Now check that we can extract a newfangle that also passes the tests!
15416 \begin_layout Plain Layout
15418 $NEWFANGLE -R./newfangle $TEX_SRC > ./new-newfangle
15421 \begin_layout Plain Layout
15423 export NEWFANGLE=./new-newfangle
15426 \begin_layout Plain Layout
15430 chunkref{test:run-tests}>
15438 \begin_layout Chunk
15442 \begin_layout Standard
15443 \begin_inset listings
15447 \begin_layout Plain Layout
15452 \begin_layout Plain Layout
15454 $NEWFANGLE -Rpca-test.awk $TEX_SRC | awk -f - || exit 1
15457 \begin_layout Plain Layout
15461 chunkref{test:cromulence}>
15464 \begin_layout Plain Layout
15468 chunkref{test:escapes}>
15471 \begin_layout Plain Layout
15475 chunkref{test:chunk-params}>
15483 \begin_layout Standard
15484 With a lyx-build-helper
15487 \begin_layout Chunk
15488 lyx-build-helper,language=sh
15491 \begin_layout Standard
15492 \begin_inset listings
15496 \begin_layout Plain Layout
15498 PROJECT_DIR="$LYX_r"
15501 \begin_layout Plain Layout
15503 LYX_SRC="$PROJECT_DIR/${LYX_i%.tex}.lyx"
15506 \begin_layout Plain Layout
15511 \begin_layout Plain Layout
15513 TEX_SRC="$TEX_DIR/$LYX_i"
15521 \begin_layout Section
15522 Extracting from the command line
15525 \begin_layout Standard
15526 First you will need the tex output, then you can extract:
15529 \begin_layout Chunk
15530 lyx-build-manual,language=sh
15533 \begin_layout Standard
15534 \begin_inset listings
15538 \begin_layout Plain Layout
15540 lyx -e latex newfangle.lyx
15543 \begin_layout Plain Layout
15545 newfangle -R./newfangle newfangle.tex > ./newfangle
15548 \begin_layout Plain Layout
15550 newfangle -R./newfangle.module newfangle.tex > ./newfangle.module
15558 \begin_layout Section
15562 \begin_layout Chunk
15566 \begin_layout Standard
15567 \begin_inset listings
15571 \begin_layout Plain Layout
15576 \begin_layout Plain Layout
15581 \begin_layout Plain Layout
15586 \begin_layout Plain Layout
15591 \begin_layout Plain Layout
15596 \begin_layout Plain Layout
15601 \begin_layout Plain Layout
15606 \begin_layout Plain Layout
15610 \begin_layout Plain Layout
15615 \begin_layout Plain Layout
15620 \begin_layout Plain Layout
15625 \begin_layout Plain Layout
15630 \begin_layout Plain Layout
15635 \begin_layout Plain Layout
15640 \begin_layout Plain Layout
15654 \begin_layout Chapter
15658 \begin_layout Chunk
15659 test:chunk-params:sub,language=,params=THING;colour
15662 \begin_layout Standard
15663 \begin_inset listings
15667 \begin_layout Plain Layout
15672 \begin_layout Plain Layout
15674 a ${THING} of colour ${colour},
15677 \begin_layout Plain Layout
15679 and looking closer =<
15681 chunkref{test:chunk-params:sub:sub}(${colour})>
15689 \begin_layout Chunk
15690 test:chunk-params:sub:sub,params=colour,language=
15693 \begin_layout Standard
15694 \begin_inset listings
15698 \begin_layout Plain Layout
15700 a funny shade of ${colour}
15708 \begin_layout Chunk
15709 test:chunk-params:text,language=
15712 \begin_layout Standard
15713 \begin_inset listings
15717 \begin_layout Plain Layout
15719 What do you see? "=<
15721 chunkref{test:chunk-params:sub}(joe, red)>"
15724 \begin_layout Plain Layout
15734 \begin_layout Standard
15735 Should generate output:
15738 \begin_layout Chunk
15739 test:chunk-params:result
15742 \begin_layout Standard
15743 \begin_inset listings
15747 \begin_layout Plain Layout
15749 What do you see? "I see a joe,
15752 \begin_layout Plain Layout
15754 a joe of colour red,
15757 \begin_layout Plain Layout
15759 and looking closer a funny shade of red"
15762 \begin_layout Plain Layout
15772 \begin_layout Standard
15773 And this chunk will perform the test:
15776 \begin_layout Chunk
15780 \begin_layout Standard
15781 \begin_inset listings
15785 \begin_layout Plain Layout
15787 $NEWFANGLE -Rtest:chunk-params:result $TEX_SRC > $TMP/answer || exit 1
15790 \begin_layout Plain Layout
15792 $NEWFANGLE -Rtest:chunk-params:text $TEX_SRC > $TMP/result || exit 1
15795 \begin_layout Plain Layout
15797 passtest diff $TMP/answer $TMP/result || (echo test:chunk-params:text failed