1 #LyX 1.6.4 created this file. For more info see http://www.lyx.org/
7 % newfangle - fully featured notangle replacement in awk
9 % Copyright (C) 2009 Sam Liddicott <sam@liddicott.com>
11 % This program is free software: you can redistribute it and/or modify
12 % it under the terms of the GNU General Public License as published by
13 % the Free Software Foundation, either version 3 of the License, or
14 % (at your option) any later version.
16 % This program is distributed in the hope that it will be useful,
17 % but WITHOUT ANY WARRANTY; without even the implied warranty of
18 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 % GNU General Public License for more details.
21 % You should have received a copy of the GNU General Public License
22 % along with this program. If not, see <http://www.gnu.org/licenses/>.
25 numbers=left, stepnumber=1, numbersep=5pt,
27 basicstyle=\footnotesize\ttfamily,
33 \use_default_options true
42 \font_typewriter default
43 \font_default_family default
50 \paperfontsize default
53 \pdf_title "Newfangle"
54 \pdf_author "Sam Liddicott"
55 \pdf_subject "Literate Programing"
56 \pdf_keywords "notangle noweb noweave literate programming cweb"
58 \pdf_bookmarksnumbered false
59 \pdf_bookmarksopen false
60 \pdf_bookmarksopenlevel 1
72 \paperorientation portrait
75 \paragraph_separation skip
77 \quotes_language english
80 \paperpagestyle default
81 \tracking_changes false
101 \begin_layout Chapter*
105 \begin_layout Standard
110 is a tool for newfangled literate programming.
111 Newfangled is defined as
113 New and often needlessly novel
117 TheFreeDictionary.com
122 \begin_layout Standard
123 In this case, newfangled means yet another new and improved method for literate
127 \begin_layout Standard
132 has a long history starting with the great
136 himself, whose literate programming tools seem to make use of as many escape
137 sequences for semantic markup as TeX itself.
140 \begin_layout Standard
149 set of tools (notangle, noweave and noroots) and helpfully reduced the
150 amount of magic character sequences to pretty much just
151 \begin_inset Flex CharStyle:Code
154 \begin_layout Plain Layout
161 \begin_inset Flex CharStyle:Code
164 \begin_layout Plain Layout
170 , and in doing so brought the wonders of literate programming within my
174 \begin_layout Standard
175 While using the LyX editor for LaTeX editing I had various troubles with
176 the noweb tools, some of which were my fault, some of which were noweb's
177 fault and some of which were LyX's fault.
180 \begin_layout Standard
185 generally brought literate programming to the masses through removing some
186 of the complexity of the original literate programming, but this would
187 be of no advantage to me if the LyX / LaTeX combination brought more complicati
191 \begin_layout Standard
196 was thus born --- as an awk replacement for notangle, adding some important
197 features, like better integration with LyX and LaTeX, multiple output format
198 conversions, and fixing notangle bugs like indentation when using -L for
202 \begin_layout Standard
203 Significantly, newfangle is just one program which replaces various programs
205 Noweave is done away with and implemented directly as LaTeX macros, and
206 noroots is implemented as a function of the untangler
213 \begin_layout Standard
214 Newfangle is written in awk for portability reasons, awk being available
216 A python conversion will probably be attempted for the benefit of LyX.
217 (Hasn't anyone implemented awk in python yet?)
220 \begin_layout Standard
221 As an extension to many literate-programming styles, Newfangle permits code
222 chunks to take parameters and thus operate somewhat like C pre-processor
223 macros, or like C++ templates.
226 \begin_layout Section*
230 \begin_layout Enumerate
231 ^^ is always going to be a problem, see texbytopic 1.2.2 (Work out what I
235 \begin_layout Enumerate
236 copy over up to date Makefile guide from noweb-lyx document
239 \begin_layout Enumerate
240 Make chunk-name settings only apply to chunks with that name
243 \begin_layout Enumerate
244 indent of multi-line chunks may be mode dependant (i.e.
245 not in string literals)
248 \begin_layout Enumerate
249 add support for other commands in =<...>, starting with
251 label which takes the line-number within the chunk, and maybe should also
252 take the chunk name/page
255 \begin_layout Enumerate
256 cant have listing inside a ruled box
259 \begin_layout Enumerate
260 when a parameterized chunk is included as well as the #line emission, say
261 what the paremeters were for that invocation.
264 \begin_layout Enumerate
267 chunkref[3]{preamble} to include a certain chunk needs to work in newfangle.awk
268 instead of failing to be recognized at all
271 \begin_layout Enumerate
272 make in-listins labels track the chunk ref too, and make
274 chunref{[2],thing}> resolve to 41c (or d, or whatever chunk the 2nd chunk
278 \begin_layout Enumerate
281 chunkref in text needs a trailing space maybe, it keeps butting up to the
285 \begin_layout Enumerate
286 because the white-space indent is output by the parent chunk, the #line
287 is that of the parent chunk.
288 White space indents must be passed to the child chunk
291 \begin_layout Chapter*
295 \begin_layout Standard
296 \begin_inset CommandInset label
302 Newfangle is licensed under the GPL 3
303 \begin_inset CommandInset citation
310 This doesn't mean that you can't use or distribute newfangle with sources
311 of an incompatible license, but it means you must make the source of newfangle
315 \begin_layout Standard
316 As newfangle is currently written in
320 , an interpreted language, this should not be too hard.
324 gpl3-copyright,language=
327 \begin_layout Standard
328 \begin_inset listings
332 \begin_layout Plain Layout
334 newfangle - fully featured notangle replacement in awk
337 \begin_layout Plain Layout
341 \begin_layout Plain Layout
343 Copyright (C) 2009 Sam Liddicott <sam@liddicott.com>
346 \begin_layout Plain Layout
350 \begin_layout Plain Layout
352 This program is free software: you can redistribute it and/or modify
355 \begin_layout Plain Layout
357 it under the terms of the GNU General Public License as published by
360 \begin_layout Plain Layout
362 the Free Software Foundation, either version 3 of the License, or
365 \begin_layout Plain Layout
367 (at your option) any later version.
370 \begin_layout Plain Layout
374 \begin_layout Plain Layout
376 This program is distributed in the hope that it will be useful,
379 \begin_layout Plain Layout
381 but WITHOUT ANY WARRANTY; without even the implied warranty of
384 \begin_layout Plain Layout
386 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
390 \begin_layout Plain Layout
392 GNU General Public License for more details.
395 \begin_layout Plain Layout
399 \begin_layout Plain Layout
401 You should have received a copy of the GNU General Public License
404 \begin_layout Plain Layout
406 along with this program.
407 If not, see <http://www.gnu.org/licenses/>.
410 \begin_layout Plain Layout
419 \begin_layout Standard
420 \begin_inset CommandInset toc
421 LatexCommand tableofcontents
432 \begin_layout Chapter
436 \begin_layout Standard
437 Newfangle is a replacement for noweb, which consists of
438 \begin_inset Flex CharStyle:Code
441 \begin_layout Plain Layout
448 \begin_inset Flex CharStyle:Code
451 \begin_layout Plain Layout
458 \begin_inset Flex CharStyle:Code
461 \begin_layout Plain Layout
470 \begin_layout Standard
472 \begin_inset Flex CharStyle:Code
475 \begin_layout Plain Layout
482 \begin_inset Flex CharStyle:Code
485 \begin_layout Plain Layout
491 it can read multiple named files, or from stdin.
494 \begin_layout Section
498 \begin_layout Standard
499 The -r option causes newfangle to behave like noroots.
502 \begin_layout LyX-Code
503 newfangle -r filename.tex
506 \begin_layout Standard
507 will print out the newfangle roots of a tex file.
511 \begin_layout Standard
513 \begin_inset Flex CharStyle:Code
516 \begin_layout Plain Layout
522 command, the roots are not enclosed in
523 \begin_inset Flex CharStyle:Code
526 \begin_layout Plain Layout
532 , unless at least one of the roots is defined using the
533 \begin_inset Flex CharStyle:Code
536 \begin_layout Plain Layout
543 \begin_inset Flex CharStyle:Code
546 \begin_layout Plain Layout
555 \begin_layout Standard
556 Also, unlike noroots, it prints out all roots --- not just those that are
558 I find that a root not being used, doesn't make it particularly top level,
559 and so-called top level roots could also be included in another root as
564 \begin_layout Standard
565 My convention is that top level roots to be extracted begin with
566 \begin_inset Flex CharStyle:Code
569 \begin_layout Plain Layout
575 and have the form of a filename.
578 \begin_layout Standard
579 Makefile.inc, discussed in
580 \begin_inset CommandInset ref
582 reference "cha:makefile.inc"
586 , can automatically extract all such sources.
589 \begin_layout Section
593 \begin_layout Standard
595 \begin_inset Flex CharStyle:Code
598 \begin_layout Plain Layout
605 \begin_inset Flex CharStyle:Code
608 \begin_layout Plain Layout
614 options are supported.
617 \begin_layout Standard
618 The standard way to extract a file would be:
621 \begin_layout LyX-Code
622 newfangle -R./Makefile.inc newfangle.tex > ./Makefile.inc
625 \begin_layout Standard
627 \begin_inset Flex CharStyle:Code
630 \begin_layout Plain Layout
637 \begin_inset Flex CharStyle:Code
640 \begin_layout Plain Layout
646 option does not break indenting.
649 \begin_layout Standard
650 Also, thanks to mode tracking (described in
651 \begin_inset CommandInset ref
653 reference "cha:modes"
658 \begin_inset Flex CharStyle:Code
661 \begin_layout Plain Layout
667 option does not interrupt (and break) multi-line C macros either.
670 \begin_layout Standard
671 This does mean that sometimes the compiler might calculate the source line
672 wrongly when generating error messages in such cases, but there isn't any
673 other way around if multi-line macros include other chunks.
676 \begin_layout Section
677 Formatting source in LaTeX
680 \begin_layout Standard
681 The noweave replacement is a set of LaTeX macros dependant upon
685 , and which can be included with:
688 \begin_layout LyX-Code
691 usepackage{newfangle.sty}
694 \begin_layout Standard
695 The LaTeX macros are shown in section
696 \begin_inset CommandInset ref
698 reference "sec:Latex-Macros"
702 , and are part of a LyX module file
703 \begin_inset Flex CharStyle:Code
706 \begin_layout Plain Layout
712 , which automatically includes the macros in the document pre-amble when
713 the newfangle LyX module is used.
716 \begin_layout Standard
717 Because the noweave replacement is impemented in LaTeX, there is no processing
718 stage required before running the
719 \begin_inset Flex CharStyle:Code
722 \begin_layout Plain Layout
729 LaTeX may need running two or more times, so that the code chunk references
730 can be fully calculated.
733 \begin_layout Standard
735 \begin_inset Flex CharStyle:Code
738 \begin_layout Plain Layout
744 package is required as it is used for formatting the code chunk captions
747 \begin_layout Standard
749 \begin_inset Flex CharStyle:Code
752 \begin_layout Plain Layout
758 package is also required, as it is used for formatting the code chunks
762 \begin_layout Standard
764 \begin_inset Flex CharStyle:Code
767 \begin_layout Plain Layout
773 package is also required.
776 \begin_layout Chapter
777 Literate Programming with Newfangle
780 \begin_layout Standard
782 Should really follow on from a part-0 explanation of what literate programming
786 \begin_layout Chapter
787 Using Newfangle with LyX
790 \begin_layout Section
794 \begin_layout Subsection
795 Installing the LyX module
798 \begin_layout Standard
800 \begin_inset Flex CharStyle:Code
803 \begin_layout Plain Layout
809 to your LyX layouts directory, which for unix users will be
810 \begin_inset Flex CharStyle:Code
813 \begin_layout Plain Layout
822 \begin_layout Standard
823 You will need to reconfigure LyX by clicking Tools\SpecialChar \menuseparator
824 Reconfigure, and then
828 \begin_layout Subsection
829 \begin_inset CommandInset label
831 name "sub:Configuring-the-build"
835 Configuring the build script
838 \begin_layout Standard
839 Make sure you don't have a conversion defined for Lyx → Program
842 \begin_layout Standard
843 From the menu Tools\SpecialChar \menuseparator
844 Preferences, add a conversion from Latex(Plain) → Program
848 \begin_layout LyX-Code
849 set -x ; newfangle -Rlyx-build $$i |
852 \begin_layout LyX-Code
853 env LYX_b=$$b LYX_i=$$i LYX_o=$$o LYX_p=$$p LYX_r=$$r bash
856 \begin_layout Standard
857 (But don't cut-n-paste it from this document or you'll be pasting a multi-line
858 string which will break your lyx preferences file).
862 \begin_layout Standard
863 I hope that one day, LyX will set these into the environment when calling
867 \begin_layout Standard
868 You may also want to consider adding options to this conversion\SpecialChar \ldots{}
872 \begin_layout LyX-Code
873 parselog=/usr/share/lyx/scripts/listerrors
876 \begin_layout Standard
877 \SpecialChar \ldots{}
878 but if you do you will lose your stderr
882 \begin_layout Plain Layout
883 There is some bash plumbing to get a copy of stderr but this footnote is
892 \begin_layout Standard
893 Now, a shell script chunk called
894 \begin_inset Flex CharStyle:Code
897 \begin_layout Plain Layout
903 will be extracted and run whenever you choose the Document\SpecialChar \menuseparator
908 \begin_layout Standard
909 The lyx-build script for this document is in section
910 \begin_inset CommandInset ref
912 reference "lyx-build-script"
916 and on a unix system will extract
917 \begin_inset Flex CharStyle:Code
920 \begin_layout Plain Layout
927 \begin_inset Flex CharStyle:Code
930 \begin_layout Plain Layout
936 awk script, and run some basic tests.
938 \begin_inset Note Note
941 \begin_layout Plain Layout
942 cross-ref to test chapter when it is a chapter all on its own
950 \begin_layout Subsection
951 Preparing your Lyx document
954 \begin_layout Standard
955 It is not necessary to base your literate document on any of the original
956 LyX literate classes; so select a regular class for your document type.
959 \begin_layout Standard
975 \begin_layout Standard
976 In the drop-down style listbox you should notice a new style defined, called
984 \begin_layout Standard
985 When you wish to insert a literate chunk, you enter it's plain name in the
986 Chunk style, instead of the older method that used
987 \begin_inset Flex CharStyle:Code
990 \begin_layout Plain Layout
997 Following the chunk name, you insert a listing with: Insert\SpecialChar \menuseparator
1001 \begin_layout Standard
1002 Inside the white listing box you can type (or paste using shift+ctrl+V)
1004 There is not need to use ctrl+enter at the end of lines as with some older
1005 LyX literate techniques --- just press enter as normal.
1008 \begin_layout Subsubsection
1009 Customising the listing appearance
1012 \begin_layout Standard
1013 In the final document, the code is formatted using the
1018 The chunk style doesn't just define the chunk name, but can also define
1019 any other chunk options supported by the lstlistings package
1020 \begin_inset Flex CharStyle:Code
1023 \begin_layout Plain Layout
1032 In fact, what you type in the chunk style is raw latex.
1033 If you want to set the chunk language without having to right-click the
1035 \begin_inset Flex CharStyle:Code
1038 \begin_layout Plain Layout
1044 after the chunk name.
1045 (Currently the language will affect all subsequent listings, so you may
1047 \begin_inset Flex CharStyle:Code
1050 \begin_layout Plain Layout
1057 \begin_inset Note Note
1060 \begin_layout Plain Layout
1069 \begin_layout Standard
1070 Of course you can do this by editing the listings box advanced properties
1071 by right-clicking on the listings box, but that takes longer, and you can't
1072 see at-a-glance what the advanced settings are while editing the document;
1073 also advanced settings apply only to that box --- the chunk settings apply
1074 through the rest of the document
1078 \begin_layout Plain Layout
1079 It ought to apply only to subsequent chunks of the same name.
1086 \begin_inset Note Note
1089 \begin_layout Plain Layout
1090 So make sure they only apply to chunks of that name
1098 \begin_layout Subsubsection
1099 Global customisations
1102 \begin_layout Standard
1107 is used to set the code chunks, it's
1108 \begin_inset Flex CharStyle:Code
1111 \begin_layout Plain Layout
1119 command can be used in the pre-amble to set some document wide settings.
1122 \begin_layout Standard
1123 If your source has many words with long sequences of capital letters, then
1125 \begin_inset Flex CharStyle:Code
1128 \begin_layout Plain Layout
1129 columns=fullflexible
1134 may be a good idea, or the capital letters will get crowded.
1135 (I think lstlistings ought to use a slightly smaller font for captial letters
1136 so that they still fit).
1139 \begin_layout Standard
1141 \begin_inset Flex CharStyle:Code
1144 \begin_layout Plain Layout
1152 looks more normal for code, but has no bold (an alternate typewriter font
1157 \begin_layout Standard
1159 \begin_inset Flex CharStyle:Code
1162 \begin_layout Plain Layout
1170 , I must also specify
1171 \begin_inset Flex CharStyle:Code
1174 \begin_layout Plain Layout
1175 columns=fullflexible
1180 or the wrong letter spacing is used.
1183 \begin_layout Standard
1184 In my LeTeX pre-amble I usually specialise my code format with:
1188 document-preamble,language=tex
1191 \begin_layout Standard
1192 \begin_inset listings
1196 \begin_layout Plain Layout
1203 \begin_layout Plain Layout
1205 numbers=left, stepnumber=1, numbersep=5pt,
1208 \begin_layout Plain Layout
1213 \begin_layout Plain Layout
1222 \begin_layout Plain Layout
1229 \begin_layout Plain Layout
1234 \begin_layout Plain Layout
1236 columns=fullflexible,
1239 \begin_layout Plain Layout
1241 numberfirstline=true
1244 \begin_layout Plain Layout
1254 \begin_layout Standard
1256 \begin_inset Flex CharStyle:Code
1259 \begin_layout Plain Layout
1269 can be impossibly difficult and amazingly easy.
1270 I spent many hours at it, following complicated instructions from those
1271 who had spend many hours over it, and was finally delivered the simple
1276 \begin_layout Plain Layout
1282 on the lyx mailing list.
1285 \begin_layout Section
1289 \begin_layout Standard
1290 The simple way was to add this to my preamble:
1293 \begin_layout LyX-Code
1299 \begin_layout LyX-Code
1307 \begin_layout Section
1311 \begin_layout Standard
1312 The next simplest way was to use ams poor-mans-bold, and add this to the
1316 \begin_layout LyX-Code
1322 \begin_layout LyX-Code
1330 \begin_layout LyX-Code
1333 pmb be the command for bold, forgot how, sorry
1336 \begin_layout Standard
1337 It works, but looks wretched on the dvi viewer.
1340 \begin_layout Section
1344 \begin_layout Standard
1349 documention suggests using Luximono.
1352 \begin_layout Standard
1353 Luximono was installed according to the instructions in Ubuntu Forums: http://ub
1354 untuforums.org/showthread.php?t=1159181 with tips from http://miknight.blogspot.com/
1356 \begin_inset space \hspace{}
1360 11/how-to-install-luxi-mono-font-in.html stating that:
1363 \begin_layout LyX-Code
1364 sudo updmap --enable MixedMap ul9.map
1367 \begin_layout Standard
1371 \begin_layout Standard
1372 It looks fine in PDF and PS view but still looks rotten in dvi view.
1375 \begin_layout Chapter
1376 Newfangle with Makefiles
1379 \begin_layout Standard
1380 \begin_inset CommandInset label
1382 name "cha:makefile.inc"
1387 \begin_inset Note Note
1390 \begin_layout Plain Layout
1391 This chapter needs revising
1397 \begin_inset Note Greyedout
1400 \begin_layout Plain Layout
1401 This chapter needs revising
1406 Here we describe a Makefile.inc that you can include in your own Makefiles,
1407 or glue as a recursive make to other projects.
1410 \begin_layout Standard
1411 The Makefile.inc described here was put together for a Samba4 vfs module,
1412 but can be used in any Make project, including automake projects.
1415 \begin_layout Section
1416 A word about makefiles formats
1419 \begin_layout Standard
1420 Whitespace formatting is very important in a Makefile.
1421 The first character of each command line must be a TAB.
1424 \begin_layout LyX-Code
1425 target: pre-requisite
1426 \begin_inset Newline newline
1430 \begin_inset Newline newline
1436 \begin_layout Standard
1437 But a TAB is pretty hard to enter into most of the Lyx formats and insets
1439 An alternative is to use a semi-colon after the pre-requisite, and a backslash
1440 at the end of each line (except the last).
1441 Then any whitespace (or none) can prefix each action.
1444 \begin_layout LyX-Code
1445 target: pre-requisite ;
1448 \begin_inset Newline newline
1454 \begin_inset Newline newline
1460 \begin_layout Standard
1461 This is the style that we use and it works pretty well for GNU make at least.
1464 \begin_layout Standard
1465 We also adopt a convention that code chunks whose names beginning with ./
1466 should always be automatically extracted from the document.
1467 Code chunks whose names do not begin with ./ are for internal reference.
1468 (This doesn't prevent such chunks from being extracted directly).
1471 \begin_layout Section
1472 Boot-strapping the extraction
1475 \begin_layout Subsection
1479 \begin_layout Standard
1480 \begin_inset CommandInset label
1482 name "sub:Bootstrap-Using-a-Makefile"
1486 It seems convenient to have the makefile extract or update the C source
1487 files as part of it's operation.
1488 It also seems convenient to have the makefile itself extracted from this
1492 \begin_layout Standard
1493 It would also be convenient to have the code to extract the makefile from
1494 this document to also be part of this document, however we have to start
1495 somewhere and this unfortunately requires us to type at least a few words
1496 by hand to start things off.
1499 \begin_layout Standard
1500 Therefore we will have a minimal root fragment, which, when extracted, can
1501 cope with extracting the rest of the source.
1502 perhaps with this shell script, which could be called
1507 \begin_inset Note Note
1510 \begin_layout Plain Layout
1511 FIX THIS CHUNK AND TEST IT
1523 \begin_layout Standard
1524 \begin_inset listings
1528 \begin_layout Plain Layout
1533 \begin_layout Plain Layout
1537 \begin_layout Plain Layout
1539 MAKE_SRC="${1:-${NW_LYX:-../../noweb-lyx/noweb-lyx3.lyx}}"
1542 \begin_layout Plain Layout
1544 MAKE_SRC=`dirname "$MAKE_SRC"`/`basename "$MAKE_SRC" .lyx`
1547 \begin_layout Plain Layout
1549 NOWEB_SRC="${2:-${NOWEB_SRC:-$MAKE_SRC.lyx}}"
1552 \begin_layout Plain Layout
1554 lyx -e latex $MAKE_SRC
1557 \begin_layout Plain Layout
1561 \begin_layout Plain Layout
1563 newfangle -R./Makefile.inc ${MAKE_SRC}.tex
1568 \begin_layout Plain Layout
1570 | sed "/NEWFANGLE_SOURCE=/s/^/#/;T;aNOWEB_SOURCE=$NEWFANGLE_SRC"
1575 \begin_layout Plain Layout
1577 | cpif ./Makefile.inc
1580 \begin_layout Plain Layout
1584 \begin_layout Plain Layout
1586 make -f ./Makefile.inc newfangle_sources
1594 \begin_layout Standard
1595 The general Makefile can be invoked with
1599 and can also be included into any automake file to automatically re-generate
1603 \begin_layout Standard
1608 can be extracted with this command:
1611 \begin_layout LyX-Code
1612 lyx -e latex newfangle.lyx &&
1617 \begin_layout LyX-Code
1618 newfangle newfangle.lyx > ./autoboot
1621 \begin_layout Standard
1622 This looks simple enough, but as mentioned, newfangle has to be had from
1623 somewhere before it can be extracted.
1626 \begin_layout Subsection
1627 \begin_inset Note Note
1630 \begin_layout Plain Layout
1631 MERGE THIS WITH THE SECTIONS OF THIS DOCUMENT
1636 \SpecialChar \ldots{}
1640 \begin_layout Standard
1641 When the lyx-build chunk is executed, the current directory will be a temporary
1643 \begin_inset Flex CharStyle:Code
1646 \begin_layout Plain Layout
1652 will refer to the tex file in this temporary directory.
1653 This is unfortunate as our makefile wants to run from the project directory
1654 where the Lyx file is kept.
1657 \begin_layout Standard
1658 We can extract the project directory from $$r, and derive the probable Lyx
1659 filename from the noweb file that Lyx generated.
1666 \begin_layout Standard
1667 \begin_inset listings
1671 \begin_layout Plain Layout
1673 PROJECT_DIR="$LYX_r"
1676 \begin_layout Plain Layout
1678 LYX_SRC="$PROJECT_DIR/${LYX_i%.tex}.lyx"
1681 \begin_layout Plain Layout
1686 \begin_layout Plain Layout
1688 TEX_SRC="$TEX_DIR/$LYX_i"
1696 \begin_layout Standard
1697 And then we can define a lyx-build fragment similar to the autoboot fragment
1704 \begin_layout Standard
1705 \begin_inset listings
1709 \begin_layout Plain Layout
1714 \begin_layout Plain Layout
1718 chunkref{lyx-build-helper}>
1721 \begin_layout Plain Layout
1723 cd $PROJECT_DIR || exit 1
1726 \begin_layout Plain Layout
1730 \begin_layout Plain Layout
1732 #/usr/bin/newfangle -filter ./notanglefix-filter
1737 \begin_layout Plain Layout
1739 # -R./Makefile.inc "../../noweb-lyx/noweb-lyx3.lyx"
1744 \begin_layout Plain Layout
1746 # | sed '/NOWEB_SOURCE=/s/=.*/=samba4-dfs.lyx/'
1751 \begin_layout Plain Layout
1756 \begin_layout Plain Layout
1761 \begin_layout Plain Layout
1763 #make -f ./Makefile.inc newfangle_sources
1771 \begin_layout Section
1775 \begin_layout Subsection
1776 Including Makefile.inc
1779 \begin_layout Standard
1780 \begin_inset CommandInset label
1782 name "sub:Keeping-extracted-files"
1786 Makefile.inc will cope with extracting all the other source files from this
1787 document and keeping them up to date.
1791 \begin_layout Standard
1792 It may also be included by a Makefile or Makefile.am defined in a Lyx document
1793 to automatically deal with the extraction of source files and documents.
1796 \begin_layout Standard
1797 A makefile has two parts; variables must be defined before the targets that
1805 \begin_layout Standard
1806 \begin_inset listings
1810 \begin_layout Plain Layout
1814 chunkref{Makefile.inc-vars}>
1817 \begin_layout Plain Layout
1821 chunkref{Makefile.inc-targets}>
1829 \begin_layout Standard
1831 \begin_inset Flex CharStyle:Code
1834 \begin_layout Plain Layout
1840 to hold the name of this Lyx file.
1847 \begin_layout Standard
1848 \begin_inset listings
1852 \begin_layout Plain Layout
1857 \begin_layout Plain Layout
1859 LITERATE_SOURCE=$(LYX_SOURCE)
1867 \begin_layout Subsection
1868 Recursive use of Makefile.inc
1871 \begin_layout Standard
1872 The makefile glue described here is used when building Samba4 vfs modules.
1875 \begin_layout Standard
1876 If you are defining a module of an existing program you may find it easier
1877 to use a slight recursive make instead of including the makefile directly.
1878 This way there is less chance of definitions in Makefile.inc interfering
1879 with definitions in the main makefile, or with definitions in other Makefile.inc
1880 from other noweb modules.
1883 \begin_layout Standard
1884 The glue works by adding a .PHONY target to call the recursive make, and
1885 adding this target as an additional pre-requisite to the existing targets.
1888 \begin_layout Standard
1889 In this example, the existing build system already has a build target for
1891 \begin_inset Flex CharStyle:Code
1894 \begin_layout Plain Layout
1900 , so we just add another pre-requisite to that.
1902 \begin_inset Flex CharStyle:Code
1905 \begin_layout Plain Layout
1911 as a pre-requisite, the stamp file's modified time indicating when all
1912 sources were extracted.
1919 \begin_layout Standard
1920 \begin_inset listings
1924 \begin_layout Plain Layout
1926 $(example_srcdir)/example.o: $(example_srcdir)/example.tex.stamp
1934 \begin_layout Standard
1935 The target for this new pre-requisite is generated by a recursive make using
1936 Makefile.inc which will make sure that the source is up to date, before
1937 it is built by the main projects makefile.
1944 \begin_layout Standard
1945 \begin_inset listings
1949 \begin_layout Plain Layout
1951 $(example_srcdir)/example.tex.stamp: $(example_srcdir)/example.tex ;
1956 \begin_layout Plain Layout
1958 cd $(example_srcdir) &&
1963 \begin_layout Plain Layout
1965 $(MAKE) -f Makefile.inc newfangle_sources
1973 \begin_layout Standard
1974 We can do similar glue for the docs, clean and distclean targets.
1975 In this example our build system is using a double colon for these targets,
1976 so we use the same in our glue.
1983 \begin_layout Standard
1984 \begin_inset listings
1988 \begin_layout Plain Layout
1993 \begin_layout Plain Layout
1995 .PHONY: docs_example
1998 \begin_layout Plain Layout
2000 docs_example:: ; cd $(example_srcdir) &&
2005 \begin_layout Plain Layout
2007 $(MAKE) -f Makefile.inc docs
2010 \begin_layout Plain Layout
2014 \begin_layout Plain Layout
2016 clean:: clean_example
2019 \begin_layout Plain Layout
2021 .PHONEY: clean_example
2024 \begin_layout Plain Layout
2026 clean_example: ; cd $(example_srcdir) &&
2031 \begin_layout Plain Layout
2033 $(MAKE) -f Makefile.inc clean
2036 \begin_layout Plain Layout
2040 \begin_layout Plain Layout
2042 distclean:: distclean_example
2045 \begin_layout Plain Layout
2047 .PHONY: distclean_example
2050 \begin_layout Plain Layout
2052 distclean_example: ; cd $(example_srcdir) &&
2057 \begin_layout Plain Layout
2059 $(MAKE) -f Makefile.inc distclean
2067 \begin_layout Standard
2068 We could do similarly for install targets to install the generated docs.
2071 \begin_layout Subsection
2072 \begin_inset CommandInset label
2074 name "sub:Converting-from-Lyx"
2078 Converting from Lyx to LaTeX
2081 \begin_layout Standard
2082 The first stage will always be to convert the Lyx file to a LaTeX file;
2083 this must be so not only because newfangle needs to to run on a TeX file,
2084 but also because the Lyx command
2086 server-goto-file-line
2090 \begin_layout Plain Layout
2093 server-goto-file-line
2095 is used to position the Lyx cursor at the compiler errors.
2102 insists that the line number provided is a line in the TeX file, and always
2103 reverse maps this to derive the line in the Lyx docment.
2104 \begin_inset Note Note
2107 \begin_layout Plain Layout
2108 The tex file should probably be an automake extra dist sources or something,
2109 so that it gets produced and packaged by make dist
2117 \begin_layout Standard
2118 The command [[lyx -e literate noweb-lyx.lyx]] will produce [[noweb-lyx.nw]]
2119 a tex file, so we define the noweb target to be the same as the Lyx file
2120 but with the .nw extension.
2127 \begin_layout Standard
2128 \begin_inset listings
2132 \begin_layout Plain Layout
2134 TEX_SOURCE=$(LYX_SOURCE:.lyx=.tex)
2143 Makefile.inc-targets
2146 \begin_layout Standard
2147 \begin_inset listings
2151 \begin_layout Plain Layout
2153 $(TEX_SOURCE): $(LYX_SOURCE) ;
2158 \begin_layout Plain Layout
2163 \begin_layout Plain Layout
2165 clean_tex: ; rm -f -- $(TEX_SOURCE)
2173 \begin_layout Subsection
2174 Extracting Program Source
2177 \begin_layout Standard
2178 The program source is extracted using newfangle, which is designed to operate
2179 on a LaTeX document.
2187 \begin_layout Standard
2188 \begin_inset listings
2192 \begin_layout Plain Layout
2194 NEWFANGLE_SOURCE=$(TEX_SOURCE)
2202 \begin_layout Standard
2203 The Lyx document can result in any number of source documents, but not all
2204 of these will be changed each time the Lyx document is updated.
2205 We certainly don't want to update the timestamps of these files and cause
2206 the whole source tree to be recompiled just because the Lyx document was
2211 \begin_layout Standard
2212 To solve this problem we use a stamp file which is always updated each time
2213 the sources are extracted from the LaTeX document.
2214 If the stamp file is older than the LaTeX document, then we can make an
2215 attempt to re-extract the sources.
2222 \begin_layout Standard
2223 \begin_inset listings
2227 \begin_layout Plain Layout
2229 NEWFANGLE_SOURCE_STAMP=$(NEWFANGLE_SOURCE).stamp
2238 Makefile.inc-targets
2241 \begin_layout Standard
2242 \begin_inset listings
2246 \begin_layout Plain Layout
2248 $(NEWFANGLE_SOURCE_STAMP): $(NEWFANGLE_SOURCE)
2253 \begin_layout Plain Layout
2255 $(NEWFANGLE_SOURCES) ;
2260 \begin_layout Plain Layout
2262 echo > $(NEWFANGLE_SOURCE_STAMP)
2265 \begin_layout Plain Layout
2267 clean_stamp: ; rm -f $(NEWFANGLE_SOURCE_STAMP)
2270 \begin_layout Plain Layout
2280 \begin_layout Subsection
2281 Extracting C sources
2284 \begin_layout Standard
2286 \begin_inset Flex CharStyle:Code
2289 \begin_layout Plain Layout
2295 to hold the names of all the C source files defined in this document.
2296 We compute this only once, by means of := in assignent.
2297 The sed deletes the any <
2298 \begin_inset space \hspace*{}
2303 \begin_inset space \hspace*{}
2307 > which may surround the roots names (for noroots compatibility).
2311 \begin_layout Standard
2312 As we use chunk names beginning with ./ to denote top level fragments that
2313 should be extracted, we filter out all fragments that do not begin with
2321 \begin_layout Standard
2322 \begin_inset listings
2326 \begin_layout Plain Layout
2335 \begin_layout Plain Layout
2337 NEWFANGLE_SOURCES:=$(shell
2342 \begin_layout Plain Layout
2344 newfangle -r $(NEWFANGLE_SOURCE) |
2349 \begin_layout Plain Layout
2351 sed -e 's/^[<][<]//;s/[>][>]$$//;/^$(NEWFANGLE_PREFIX)/!d'
2356 \begin_layout Plain Layout
2358 -e 's/^$(NEWFANGLE_PREFIX)/
2365 \begin_layout Plain Layout
2376 Makefile.inc-targets
2379 \begin_layout Standard
2380 \begin_inset listings
2384 \begin_layout Plain Layout
2386 .PHONY: echo_newfangle_sources
2389 \begin_layout Plain Layout
2391 echo_newfangle_sources: ; @echo $(NEWFANGLE_SOURCES)
2399 \begin_layout Standard
2400 We define a convenient target called
2401 \begin_inset Flex CharStyle:Code
2404 \begin_layout Plain Layout
2410 to re-extract the source if the LaTeX file has been updated.
2414 Makefile.inc-targets
2417 \begin_layout Standard
2418 \begin_inset listings
2422 \begin_layout Plain Layout
2424 .PHONY: newfangle_sources
2427 \begin_layout Plain Layout
2429 newfangle_sources: $(NEWFANGLE_SOURCE_STAMP)
2437 \begin_layout Standard
2438 And also a convenient target to remove extracted sources.
2442 Makefile.inc-targets
2445 \begin_layout Standard
2446 \begin_inset listings
2450 \begin_layout Plain Layout
2452 .PHONY: clean_newfangle_sources
2455 \begin_layout Plain Layout
2457 clean_newfangle_sources: ;
2462 \begin_layout Plain Layout
2464 rm -f -- $(NEWFANGLE_SOURCE_STAMP) $(NEWFANGLE_SOURCES)
2472 \begin_layout Standard
2474 \begin_inset Flex CharStyle:Code
2477 \begin_layout Plain Layout
2483 macro takes 4 arguments: the filename (1), some extensions to match (2)
2484 and a some shell command to return if the filename matches the exentions
2492 \begin_layout Standard
2493 \begin_inset listings
2497 \begin_layout Plain Layout
2499 if_extension=$(if $(findstring $(suffix $(1)),$(2)),$(3),$(4))
2507 \begin_layout Standard
2508 For some source files like C files, we want to output the line number and
2509 filename of the original LaTeX document from which the source came.
2512 \begin_layout Standard
2513 To make this easier we define the file extensions for which we want to do
2521 \begin_layout Standard
2522 \begin_inset listings
2526 \begin_layout Plain Layout
2536 \begin_layout Standard
2537 We can then use the if_extensions macro to define a macro which expands
2539 \begin_inset Flex CharStyle:Code
2542 \begin_layout Plain Layout
2548 option if newfangle is being invoked in a C source file, so that C compile
2549 errors will refer to the line number in the Lyx document.
2557 \begin_layout Standard
2558 \begin_inset listings
2562 \begin_layout Plain Layout
2567 \begin_layout Plain Layout
2569 nf_line=-L -T$(TABS)
2572 \begin_layout Plain Layout
2579 \begin_layout Plain Layout
2581 $(call if_extension,$(2),$(C_EXTENSIONS),$(nf_line))
2586 \begin_layout Plain Layout
2596 \begin_layout Standard
2597 We can use a similar trick to define an
2601 macro which takes just the filename as an argument and can return a pipeline
2602 stage calling the indent command.
2603 Indent can be turned off with
2604 \begin_inset Flex CharStyle:Code
2607 \begin_layout Plain Layout
2608 make newfangle_sources indent=
2620 \begin_layout Standard
2621 \begin_inset listings
2625 \begin_layout Plain Layout
2627 indent_options=-npro -kr -i8 -ts8 -sob -l80 -ss -ncs
2630 \begin_layout Plain Layout
2632 indent=$(call if_extension,$(1),$(C_EXTENSIONS),
2637 \begin_layout Plain Layout
2639 | indent $(indent_options))
2647 \begin_layout Standard
2648 We now define the pattern for extracting a file.
2649 The files are written using noweb's
2655 \begin_layout Plain Layout
2658 So you still need noweb installed in order to use cpif
2664 \begin_inset Note Note
2667 \begin_layout Plain Layout
2670 Write an awk version
2677 so that the file timestamp will not be touched if the contents haven't
2679 This avoids the need to rebuild the entire project because of a typographical
2680 change in the documentation, or if only a few C source files have changed.
2687 \begin_layout Standard
2688 \begin_inset listings
2692 \begin_layout Plain Layout
2694 newfangle_extract=@mkdir -p $(dir $(1)) &&
2699 \begin_layout Plain Layout
2701 $(call newfangle,$(2),$(1)) > "$(1).tmp" &&
2706 \begin_layout Plain Layout
2708 cat "$(1).tmp" $(indent) | cpif "$(1)"
2713 \begin_layout Plain Layout
2715 && rm -- "$(1).tmp" ||
2720 \begin_layout Plain Layout
2722 (echo error newfangling $(1) from $(2) ; exit 1)
2730 \begin_layout Standard
2731 We define a target which will extract or update all sources.
2732 To do this we first defined a makefile template that can do this for any
2733 source file in the LaTeX document.
2740 \begin_layout Standard
2741 \begin_inset listings
2745 \begin_layout Plain Layout
2747 define NEWFANGLE_template
2750 \begin_layout Plain Layout
2757 \begin_layout Plain Layout
2759 $$(call newfangle_extract,$(1),$(2))
2762 \begin_layout Plain Layout
2764 NEWFANGLE_TARGETS+=$(1)
2767 \begin_layout Plain Layout
2777 \begin_layout Standard
2778 We then enumerate the discovered
2779 \begin_inset Flex CharStyle:Code
2782 \begin_layout Plain Layout
2788 to generate a makefile rule for each one using the makefile template we
2793 Makefile.inc-targets
2796 \begin_layout Standard
2797 \begin_inset listings
2801 \begin_layout Plain Layout
2803 $(foreach source,$(NEWFANGLE_SOURCES),
2808 \begin_layout Plain Layout
2810 $(eval $(call NEWFANGLE_template,$(source),$(NEWFANGLE_SOURCE)))
2815 \begin_layout Plain Layout
2825 \begin_layout Standard
2826 These will all be built with NEWFANGLE_SOURCE_STAMP.
2829 \begin_layout Standard
2830 We also remove the generated sources on a
2838 Makefile.inc-targets
2841 \begin_layout Standard
2842 \begin_inset listings
2846 \begin_layout Plain Layout
2848 _distclean: clean_newfangle_sources
2856 \begin_layout Subsection
2857 Extracting Documentation
2860 \begin_layout Standard
2861 We then identify the intermediate stages of the documentation and their
2862 build and clean targets.
2865 \begin_layout Subsubsection
2869 \begin_layout Standard
2870 We produce a pdf file from the tex file.
2877 \begin_layout Standard
2878 \begin_inset listings
2882 \begin_layout Plain Layout
2884 NEWFANGLE_PDF=$(TEX_SOURCE:.tex=.pdf)
2892 \begin_layout Standard
2893 We run pdflatex twice to be sure that the contents and aux files are up
2895 We certainly are required to run pdflatex twice if these files do not exist!
2899 Makefile.inc-targets
2902 \begin_layout Standard
2903 \begin_inset listings
2907 \begin_layout Plain Layout
2909 $(NEWFANGLE_PDF): $(TEX_SOURCE); pdflatex $< && pdflatex $<
2912 \begin_layout Plain Layout
2914 clean_pdf: ; rm -f -- $(NEWFANGLE_PDF)
2919 \begin_layout Plain Layout
2921 $(TEX_SOURCE:.tex=.toc)
2926 \begin_layout Plain Layout
2928 $(TEX_SOURCE:.tex=.log)
2933 \begin_layout Plain Layout
2935 $(TEX_SOURCE:.tex=.aux)
2943 \begin_layout Subsubsection
2947 \begin_layout Standard
2948 Currently we only build pdf as a final format, but NEWFANGLE_DOCS may later
2949 hold other output formats.
2956 \begin_layout Standard
2957 \begin_inset listings
2961 \begin_layout Plain Layout
2963 NEWFANGLE_DOCS=$(NEWFANGLE_PDF)
2971 \begin_layout Standard
2972 We also define newfangle_docs as a convenient phony target<
2976 Makefile.inc-targets
2979 \begin_layout Standard
2980 \begin_inset listings
2984 \begin_layout Plain Layout
2986 .PHONY: newfangle_docs
2989 \begin_layout Plain Layout
2991 newfangle_docs: $(NEWFANGLE_DOCS)
2994 \begin_layout Plain Layout
2996 docs: newfangle_docs
3004 \begin_layout Standard
3005 And define a convenient clean_noweb_docs which we add to the regular clean
3010 Makefile.inc-targets
3013 \begin_layout Standard
3014 \begin_inset listings
3018 \begin_layout Plain Layout
3020 .PHONEY: clean_newfangle_docs
3023 \begin_layout Plain Layout
3025 clean_newfangle_docs: clean_tex clean_pdf
3028 \begin_layout Plain Layout
3030 clean: clean_newfangle_docs
3033 \begin_layout Plain Layout
3037 \begin_layout Plain Layout
3039 distclean_newfangle_docs: clean_tex clean_newfangle_docs
3042 \begin_layout Plain Layout
3044 distclean: clean distclean_newfangle_docs
3052 \begin_layout Subsection
3056 \begin_layout Standard
3057 If Makefile.inc is included into Makefile, then extracted files can be updated
3061 \begin_layout LyX-Code
3062 make newfangle_sources
3065 \begin_layout Standard
3069 \begin_layout LyX-Code
3070 make -f Makefile.inc newfangle_sources
3077 \begin_layout Chapter
3078 Newfangle awk source code
3081 \begin_layout Standard
3082 We use the copyright notice from chapter
3083 \begin_inset CommandInset ref
3085 reference "cha:License"
3093 ./newfangle,language=awk,morestring=[b]{/},morekeywords=else
3096 \begin_layout Standard
3097 \begin_inset listings
3101 \begin_layout Plain Layout
3106 \begin_layout Plain Layout
3110 chunkref{gpl3-copyright}>
3113 \begin_layout Plain Layout
3122 \begin_layout Standard
3123 We also use code from Arnold Robbins public domain getopt (1993 revision)
3125 \begin_inset CommandInset ref
3127 reference "cha:getopt"
3131 , and naturally want to attribute this appropriately.
3134 \begin_layout Standard
3135 \begin_inset listings
3139 \begin_layout Plain Layout
3143 \begin_layout Plain Layout
3145 # NOTE: Arnold Robbins public domain getopt for awk is also used:
3148 \begin_layout Plain Layout
3152 chunkref{getopt.awk-header}>
3155 \begin_layout Plain Layout
3159 \begin_layout Plain Layout
3163 chunkref{getopt.awk-getopt()}>
3166 \begin_layout Plain Layout
3175 \begin_layout Standard
3176 And include the following chunks
3183 \begin_layout Standard
3184 \begin_inset listings
3188 \begin_layout Plain Layout
3192 chunkref{helper-functions}>
3195 \begin_layout Plain Layout
3199 chunkref{mode-tracker}>
3202 \begin_layout Plain Layout
3206 chunkref{parse_chunk_args}>
3209 \begin_layout Plain Layout
3213 chunkref{chunk-storage-functions}>
3216 \begin_layout Plain Layout
3220 chunkref{output_chunk_names()}>
3223 \begin_layout Plain Layout
3227 chunkref{output_chunks()}>
3230 \begin_layout Plain Layout
3234 chunkref{write_chunk()}>
3237 \begin_layout Plain Layout
3241 chunkref{expand_chunk_args()}>
3244 \begin_layout Plain Layout
3251 \begin_layout Plain Layout
3255 chunkref{recognize-chunk}>
3258 \begin_layout Plain Layout
3270 \begin_layout Section
3274 \begin_layout Standard
3275 The portable way to erase an array in awk is to split the empty string,
3280 awk-delete-array,params=ARRAY
3283 \begin_layout Standard
3284 \begin_inset listings
3288 \begin_layout Plain Layout
3290 split("", ${ARRAY});
3299 dump-array,params=ARRAY
3302 \begin_layout Standard
3303 \begin_inset listings
3307 \begin_layout Plain Layout
3318 \begin_layout Plain Layout
3320 for (_x in ${ARRAY}) {
3323 \begin_layout Plain Layout
3325 print _x "=" ${ARRAY}[_x] "
3330 \begin_layout Plain Layout
3335 \begin_layout Plain Layout
3351 \begin_layout Section
3355 \begin_layout Standard
3356 Fatal errors are issued with the error function:
3360 error(),append=helper-functions
3363 \begin_layout Standard
3364 \begin_inset listings
3368 \begin_layout Plain Layout
3370 function error(message)
3373 \begin_layout Plain Layout
3378 \begin_layout Plain Layout
3380 print "ERROR: " FILENAME ":" FNR " " message > "/dev/stderr";
3383 \begin_layout Plain Layout
3388 \begin_layout Plain Layout
3398 \begin_layout Standard
3399 \begin_inset listings
3403 \begin_layout Plain Layout
3405 function warning(message)
3408 \begin_layout Plain Layout
3413 \begin_layout Plain Layout
3415 print "WARNING: " FILENAME ":" FNR " " message > "/dev/stderr";
3418 \begin_layout Plain Layout
3423 \begin_layout Plain Layout
3433 \begin_layout Chapter
3437 \begin_layout Standard
3438 LaTeX arguments to lstlistings macros are a comma seperated list of key-value
3440 Values containing commas are enclosed in
3441 \begin_inset Flex CharStyle:Code
3444 \begin_layout Plain Layout
3451 \begin_inset Flex CharStyle:Code
3454 \begin_layout Plain Layout
3460 , which is to be expected for LaTeX.
3463 \begin_layout Standard
3464 A sample expressions is:
3467 \begin_layout LyX-Code
3468 name=thomas, params={a, b}, something, something-else
3471 \begin_layout Standard
3472 but we see that this is just a simpler form of this expression:
3475 \begin_layout LyX-Code
3476 name=freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
3479 \begin_layout Standard
3480 We may consider that we need a function that can parse such LaTeX expressions
3481 and assign the values to an
3485 associated array, perhaps using a recursive parser into a multi-dimensional
3490 \begin_layout Plain Layout
3491 as AWK doesn't have nested-hash support
3499 \begin_layout Standard
3500 \begin_inset Tabular
3501 <lyxtabular version="3" rows="6" columns="2">
3503 <column alignment="left" valignment="top" width="0">
3504 <column alignment="left" valignment="top" width="0">
3506 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3509 \begin_layout Plain Layout
3515 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3518 \begin_layout Plain Layout
3526 <cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
3529 \begin_layout Plain Layout
3535 <cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3538 \begin_layout Plain Layout
3546 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3549 \begin_layout Plain Layout
3555 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3558 \begin_layout Plain Layout
3566 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3569 \begin_layout Plain Layout
3575 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3578 \begin_layout Plain Layout
3586 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
3589 \begin_layout Plain Layout
3595 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
3598 \begin_layout Plain Layout
3606 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
3609 \begin_layout Plain Layout
3615 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
3618 \begin_layout Plain Layout
3632 \begin_layout Standard
3633 Oon reflection it seems that sometimes such nesting is not desirable, as
3634 the braces are also used to delimit values that contain commas --- we may
3638 \begin_layout LyX-Code
3639 name={williamson, freddie}
3642 \begin_layout Standard
3644 \begin_inset Flex CharStyle:Code
3647 \begin_layout Plain Layout
3654 \begin_inset Flex CharStyle:Code
3657 \begin_layout Plain Layout
3666 \begin_layout Standard
3667 In fact we are not so interested in the detail so as to be bothered by this,
3668 which turns out to be a good thing for two reasons.
3669 Firstly LaTeX has a malleable parser with no strict syntax, and secondly
3671 \begin_inset Flex CharStyle:Code
3674 \begin_layout Plain Layout
3681 \begin_inset Flex CharStyle:Code
3684 \begin_layout Plain Layout
3690 should count as two items will be context dependant anyway.
3693 \begin_layout Standard
3694 We need to parse this latex for only one reason; which is that we are extending
3695 lstlistings to add some additional arguments which will be used to express
3696 chunk parameters and other chunk options.
3699 \begin_layout Section
3700 Additional lstlstings parameters
3703 \begin_layout Standard
3704 Further on we define a
3705 \begin_inset Flex CharStyle:Code
3708 \begin_layout Plain Layout
3716 LaTeX macro whose arguments will consist of a the chunk name, optionally
3717 followed by a comma and then a comma separated list of arguments.
3718 In fact we will just need to prefix
3719 \begin_inset Flex CharStyle:Code
3722 \begin_layout Plain Layout
3728 to the arguments to in order to create valid lstlistings arguments.
3732 \begin_layout Standard
3733 There will be other arguments supported too;
3736 \begin_layout Description
3737 params As an extension to many literate-programming styles, newfangle permits
3738 code chunks to take parameters and thus operate somewhat like C pre-processor
3739 macros, or like C++ templates.
3740 Chunk parameters are declared with a chunk argument called
3741 \begin_inset Flex CharStyle:Code
3744 \begin_layout Plain Layout
3750 , which holds a semi-colon separated list of parameters, like this:
3753 \begin_layout LyX-Code
3754 achunk,language=C,params=name;address
3757 \begin_layout Description
3758 addto a named chunk that this chunk is to be included into.
3759 This saves the effort of having to declare another listing of the named
3760 chunk merely to include this one.
3763 \begin_layout Standard
3765 \begin_inset Flex Chunkref
3768 \begin_layout Plain Layout
3774 will accept two paramters,
3775 \begin_inset Flex CharStyle:Code
3778 \begin_layout Plain Layout
3784 being the text to parse, and
3785 \begin_inset Flex CharStyle:Code
3788 \begin_layout Plain Layout
3794 being an array to receive the parsed values as described above.
3795 The optional parameter
3796 \begin_inset Flex CharStyle:Code
3799 \begin_layout Plain Layout
3805 is used during recursion to build up the multi-dimensional array path.
3812 \begin_layout Standard
3813 \begin_inset listings
3817 \begin_layout Plain Layout
3821 chunkref{get_chunk_args()}>
3833 \begin_layout Standard
3834 \begin_inset listings
3838 \begin_layout Plain Layout
3840 function get_chunk_args(text, values,
3843 \begin_layout Plain Layout
3845 # optional parameters
3848 \begin_layout Plain Layout
3850 path, # hierarchical precursors
3853 \begin_layout Plain Layout
3858 \begin_layout Plain Layout
3868 \begin_layout Standard
3869 The strategy is to parse the name, and then look for a value.
3870 If the value begins with a brace
3871 \begin_inset Flex CharStyle:Code
3874 \begin_layout Plain Layout
3880 , then we recurse and consume as much of the text as necessary, returning
3881 the remaining text when we encounter a leading close-brace
3882 \begin_inset Flex CharStyle:Code
3885 \begin_layout Plain Layout
3892 This being the strategy --- and executed in a loop --- we realise that
3893 we must first look for the closing brace (perhaps preceded by white space)
3894 in order to terminate the recursion, and returning remaining text.
3897 \begin_layout Standard
3898 \begin_inset listings
3902 \begin_layout Plain Layout
3907 \begin_layout Plain Layout
3909 split("", next_chunk_args);
3912 \begin_layout Plain Layout
3914 while(length(text)) {
3917 \begin_layout Plain Layout
3919 if (match(text, "^ *}(.*)", a)) {
3922 \begin_layout Plain Layout
3927 \begin_layout Plain Layout
3932 \begin_layout Plain Layout
3936 chunkref{parse-chunk-args}>
3939 \begin_layout Plain Layout
3944 \begin_layout Plain Layout
3949 \begin_layout Plain Layout
3959 \begin_layout Standard
3960 \begin_inset Note Note
3963 \begin_layout Plain Layout
3964 Use BNF package here
3969 We can see that the text could be inspected with this regex:
3976 \begin_layout Standard
3977 \begin_inset listings
3981 \begin_layout Plain Layout
3983 if (! match(text, " *([^,=]*[^,= ]) *(([,=]) *(([^,}]*) *,* *(.*))|)$", a))
3987 \begin_layout Plain Layout
3992 \begin_layout Plain Layout
4002 \begin_layout Standard
4004 \begin_inset Flex CharStyle:Code
4007 \begin_layout Plain Layout
4013 will have the following values:
4016 \begin_layout Standard
4017 \begin_inset Tabular
4018 <lyxtabular version="3" rows="7" columns="2">
4020 <column alignment="center" valignment="top" width="0">
4021 <column alignment="left" valignment="top" width="0">
4023 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
4026 \begin_layout Plain Layout
4032 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
4035 \begin_layout Plain Layout
4043 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
4046 \begin_layout Plain Layout
4052 <cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
4055 \begin_layout Plain Layout
4063 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
4066 \begin_layout Plain Layout
4072 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
4075 \begin_layout Plain Layout
4076 =freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
4083 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
4086 \begin_layout Plain Layout
4092 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
4095 \begin_layout Plain Layout
4103 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
4106 \begin_layout Plain Layout
4112 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
4115 \begin_layout Plain Layout
4116 freddie, foo={bar=baz, quux={quirk, a=fleeg}}, etc
4123 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
4126 \begin_layout Plain Layout
4132 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
4135 \begin_layout Plain Layout
4143 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
4146 \begin_layout Plain Layout
4152 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
4155 \begin_layout Plain Layout
4156 , foo={bar=baz, quux={quirk, a=fleeg}}, etc
4169 \begin_layout Standard
4171 \begin_inset Flex CharStyle:Code
4174 \begin_layout Plain Layout
4181 \begin_inset Flex CharStyle:Code
4184 \begin_layout Plain Layout
4190 and signify whether the option named in
4191 \begin_inset Flex CharStyle:Code
4194 \begin_layout Plain Layout
4200 has a value or not (respectively).
4203 \begin_layout Standard
4204 If the option does have a value, then if the expression
4205 \begin_inset Flex CharStyle:Code
4208 \begin_layout Plain Layout
4215 \begin_inset Flex CharStyle:Code
4218 \begin_layout Plain Layout
4224 it will signify that we need to recurse:
4227 \begin_layout Standard
4228 \begin_inset listings
4232 \begin_layout Plain Layout
4237 \begin_layout Plain Layout
4242 \begin_layout Plain Layout
4244 if (substr(a[4],1,1) == "{") {
4247 \begin_layout Plain Layout
4249 text = get_chunk_args(substr(a[4],2), values, path name SUBSEP);
4252 \begin_layout Plain Layout
4257 \begin_layout Plain Layout
4259 values[path name]=a[5];
4262 \begin_layout Plain Layout
4267 \begin_layout Plain Layout
4272 \begin_layout Plain Layout
4277 \begin_layout Plain Layout
4279 values[path name]="";
4282 \begin_layout Plain Layout
4287 \begin_layout Plain Layout
4297 \begin_layout Standard
4298 We can test this function like this:
4305 \begin_layout Standard
4306 \begin_inset listings
4310 \begin_layout Plain Layout
4314 chunkref{get_chunk_args()}>
4317 \begin_layout Plain Layout
4322 \begin_layout Plain Layout
4327 \begin_layout Plain Layout
4331 \begin_layout Plain Layout
4333 print get_chunk_args("name=freddie, foo={bar=baz, quux={quirk, a=fleeg}},
4337 \begin_layout Plain Layout
4342 \begin_layout Plain Layout
4344 print "a[" b "] => " a[b];
4347 \begin_layout Plain Layout
4352 \begin_layout Plain Layout
4362 \begin_layout Standard
4363 which should give this output:
4367 gca-test.awk-results
4370 \begin_layout Standard
4371 \begin_inset listings
4375 \begin_layout Plain Layout
4377 a[foo.quux.quirk] =>
4380 \begin_layout Plain Layout
4382 a[foo.quux.a] => fleeg
4385 \begin_layout Plain Layout
4390 \begin_layout Plain Layout
4395 \begin_layout Plain Layout
4405 \begin_layout Section
4406 Parsing chunk arguments
4409 \begin_layout Standard
4410 \begin_inset CommandInset label
4412 name "cha:Chunk Arguments"
4419 \begin_layout Standard
4420 Arguments to paramterized chunks are expressed in round brackets as a comma
4421 separated list of optional arguments.
4422 For example, a chunk that is defined with:
4425 \begin_layout LyX-Code
4428 Chunk{achunk, params=name ; address}
4431 \begin_layout Standard
4432 could be invoked as:
4435 \begin_layout LyX-Code
4438 chunkref{achunk}(John Jones, jones@example.com)
4441 \begin_layout Standard
4442 An argument list may be as simple as in
4443 \begin_inset Flex CharStyle:Code
4446 \begin_layout Plain Layout
4449 chunkref{pull}(thing, otherthing)
4457 \begin_layout LyX-Code
4460 chunkref{pull}(things[x, y], get_other_things(a, "(all)"))
4463 \begin_layout Standard
4464 --- which for all it's commas and quotes and parenthesis represents only
4466 \begin_inset Flex CharStyle:Code
4469 \begin_layout Plain Layout
4476 \begin_inset Flex CharStyle:Code
4479 \begin_layout Plain Layout
4480 get_other_things(a, "(all)")
4488 \begin_layout Standard
4489 If we simply split parameter list on commas, then the comma in
4490 \begin_inset Flex CharStyle:Code
4493 \begin_layout Plain Layout
4499 would split into two seperate arguments:
4500 \begin_inset Flex CharStyle:Code
4503 \begin_layout Plain Layout
4510 \begin_inset Flex CharStyle:Code
4513 \begin_layout Plain Layout
4519 --- neither of which make sense on their own.
4522 \begin_layout Standard
4523 One way to prevent this would be by refusing to split text between matching
4525 \begin_inset Flex CharStyle:Code
4528 \begin_layout Plain Layout
4535 \begin_inset Flex CharStyle:Code
4538 \begin_layout Plain Layout
4545 \begin_inset Flex CharStyle:Code
4548 \begin_layout Plain Layout
4555 \begin_inset Flex CharStyle:Code
4558 \begin_layout Plain Layout
4565 \begin_inset Flex CharStyle:Code
4568 \begin_layout Plain Layout
4575 \begin_inset Flex CharStyle:Code
4578 \begin_layout Plain Layout
4584 and most likely also
4585 \begin_inset Flex CharStyle:Code
4588 \begin_layout Plain Layout
4595 \begin_inset Flex CharStyle:Code
4598 \begin_layout Plain Layout
4605 \begin_inset Flex CharStyle:Code
4608 \begin_layout Plain Layout
4615 \begin_inset Flex CharStyle:Code
4618 \begin_layout Plain Layout
4625 Of course this also makes it impossible to pass such mis-matched code fragments
4626 as parameters, but I think that it would be hard for readers to cope with
4627 authors who would pass such code unbalanced fragments as chunk parameters
4631 \begin_layout Plain Layout
4632 I know that I couldn't cope with users doing such things, and although the
4633 GPL3 license prevents me from actually forbidding anyone from trying, if
4634 they want it to work they'll have to write the code themselves and not
4635 expect any support from me.
4643 \begin_layout Standard
4644 Unfortunately, the full set of matching delimiters may vary from language
4646 In certain C++ template contexts,
4647 \begin_inset Flex CharStyle:Code
4650 \begin_layout Plain Layout
4657 \begin_inset Flex CharStyle:Code
4660 \begin_layout Plain Layout
4666 would count as delimiters, and yet in other contexts they would not.
4669 \begin_layout Standard
4670 This puts me in the unfortunate position of having to parse-somewhat all
4671 programming languages without knowing what they are!
4674 \begin_layout Standard
4675 However, if this universal mode-tracking is possible, then parsing the arguments
4677 Such a mode tracker is described in chapter
4678 \begin_inset CommandInset ref
4680 reference "cha:modes"
4684 and used here with simplicity.
4691 \begin_layout Standard
4692 \begin_inset listings
4696 \begin_layout Plain Layout
4698 function parse_chunk_args(language, text, values, mode,
4701 \begin_layout Plain Layout
4706 \begin_layout Plain Layout
4711 \begin_layout Plain Layout
4716 \begin_layout Plain Layout
4720 chunkref{new-mode-tracker}(context, language, mode)>
4723 \begin_layout Plain Layout
4725 rest = mode_tracker(context, text, values);
4728 \begin_layout Plain Layout
4733 \begin_layout Plain Layout
4735 for(c=1; c <= context[0, "values"]; c++) {
4738 \begin_layout Plain Layout
4740 values[c] = context[0, "values", c];
4743 \begin_layout Plain Layout
4748 \begin_layout Plain Layout
4753 \begin_layout Plain Layout
4763 \begin_layout Section
4764 Expanding parameters in the text
4767 \begin_layout Standard
4768 Within the body of the chunk, the parameters are referred to with:
4769 \begin_inset Flex CharStyle:Code
4772 \begin_layout Plain Layout
4779 \begin_inset Flex CharStyle:Code
4782 \begin_layout Plain Layout
4789 There is a strong case that a LaTeX style notation should be used, like
4792 param{name} which would be expressed in the listing as =<
4794 param{name}> and be rendered as
4795 \begin_inset listings
4799 \begin_layout Plain Layout
4809 Such notation would make me go blind, but I do intend to adopt it
4813 \begin_layout Plain Layout
4814 Probably when LyX's listings inset can recognize and render it, so that
4815 I no longer have to type =<\SpecialChar \ldots{}
4824 \begin_layout Standard
4825 We therefore need a function
4826 \begin_inset Flex CharStyle:Code
4829 \begin_layout Plain Layout
4835 which will take a block of text, a list of permitted parameters, and the
4836 arguments which must substitute for the parameters.
4840 \begin_layout Standard
4841 \begin_inset CommandInset label
4843 name "Here-we-split"
4847 Here we split the text on
4848 \begin_inset Flex CharStyle:Code
4851 \begin_layout Plain Layout
4857 which means that all parts except the first will begin with a parameter
4858 name which will be terminated by
4859 \begin_inset Flex CharStyle:Code
4862 \begin_layout Plain Layout
4869 The split function will consume the literal
4870 \begin_inset Flex CharStyle:Code
4873 \begin_layout Plain Layout
4886 \begin_layout Standard
4887 \begin_inset listings
4891 \begin_layout Plain Layout
4893 function expand_chunk_args(text, params, args,
4896 \begin_layout Plain Layout
4898 p, text_array, next_text, v, t, l)
4901 \begin_layout Plain Layout
4906 \begin_layout Plain Layout
4908 if (split(text, text_array, "
4915 \begin_layout Plain Layout
4919 chunkref{substitute-chunk-args}>
4922 \begin_layout Plain Layout
4927 \begin_layout Plain Layout
4931 \begin_layout Plain Layout
4936 \begin_layout Plain Layout
4946 \begin_layout Standard
4947 First, we produce an associative array of substitution values indexed by
4949 This will serve as a cache, allowing us to look up the replacement values
4950 as we extract each name.
4954 substitute-chunk-args
4957 \begin_layout Standard
4958 \begin_inset listings
4962 \begin_layout Plain Layout
4967 \begin_layout Plain Layout
4969 v[params[p]]=args[p];
4972 \begin_layout Plain Layout
4982 \begin_layout Standard
4983 We accumulate substituted text in the variable
4984 \begin_inset Flex CharStyle:Code
4987 \begin_layout Plain Layout
4994 As the first part of the split function is the part before the delimiter
4996 \begin_inset Flex CharStyle:Code
4999 \begin_layout Plain Layout
5005 in our case --- this part will never contain a parameter reference, so
5006 we assign this directly to the result kept in
5007 \begin_inset Flex CharStyle:Code
5010 \begin_layout Plain Layout
5017 \begin_inset listings
5021 \begin_layout Plain Layout
5031 \begin_layout Standard
5032 We then iterate over the remaining values in the array
5036 \begin_layout Plain Layout
5037 I don't know why I think that it will enumerate the array in order, but
5044 \begin_inset Note Note
5047 \begin_layout Plain Layout
5048 So fix it or porve it
5053 , and substitute each reference for it's argument.
5056 \begin_layout Standard
5057 \begin_inset listings
5061 \begin_layout Plain Layout
5063 for(t=2; t in text_array; t++) {
5066 \begin_layout Plain Layout
5070 chunkref{substitute-chunk-arg}>
5073 \begin_layout Plain Layout
5083 \begin_layout Standard
5085 \begin_inset Flex CharStyle:Code
5088 \begin_layout Plain Layout
5094 a valid parameter reference will consist of valid parameter name terminated
5096 \begin_inset Flex CharStyle:Code
5099 \begin_layout Plain Layout
5106 A valid character name begins with the underscore or a letter, and may
5107 contain letters, digits or underscores.
5110 \begin_layout Standard
5111 A valid looking reference that is not actually the name of a parameter will
5112 be and not substituted.
5113 This is good because there is nothing to substitute anyway, and it avoids
5114 clashes when writing code for languages where ${\SpecialChar \ldots{}
5115 } is a valid construct
5116 --- such constructs will not be interfered with unless the parameter name
5121 substitute-chunk-arg
5124 \begin_layout Standard
5125 \begin_inset listings
5129 \begin_layout Plain Layout
5131 if (match(text_array[t], "^([a-zA-Z_][a-zA-Z0-9_]*)}", l) &&
5134 \begin_layout Plain Layout
5139 \begin_layout Plain Layout
5144 \begin_layout Plain Layout
5146 text = text v[l[1]] substr(text_array[t], length(l[1])+2);
5149 \begin_layout Plain Layout
5154 \begin_layout Plain Layout
5156 text = text "${" text_array[t];
5159 \begin_layout Plain Layout
5169 \begin_layout Chapter
5170 Language Modes & Quoting
5173 \begin_layout Standard
5174 \begin_inset CommandInset label
5183 \begin_layout Section
5187 \begin_layout Standard
5188 lstlistings and newfangle both recognize source languages, and perform some
5190 lstlistings can detect strings and comments within a language definition
5191 and perform suitable rendering, such as italics for comments, and visible-space
5195 \begin_layout Standard
5196 Newfangle similarly can recognize strings, and comments, etc, within a language,
5197 so that any chunks included with
5198 \begin_inset Flex CharStyle:Code
5201 \begin_layout Plain Layout
5209 can be suitably escape or quoted.
5212 \begin_layout Subsection
5213 Modes to keep code together
5216 \begin_layout Standard
5217 As an example, in the C language there are a few parse modes, affecting
5218 the interpretation of characters.
5221 \begin_layout Standard
5222 One parse mode is the strings mode.
5223 The string mode is commenced by an un-escaped quotation mark
5224 \begin_inset Flex CharStyle:Code
5227 \begin_layout Plain Layout
5233 and terminated by the same.
5234 Within the string mode, only one additional mode can be commenced, it is
5236 \begin_inset Flex CharStyle:Code
5239 \begin_layout Plain Layout
5247 , which is always terminated by the folloing character.
5250 \begin_layout Standard
5252 \begin_inset Flex CharStyle:Code
5255 \begin_layout Plain Layout
5261 which is terminated by a
5262 \begin_inset Flex CharStyle:Code
5265 \begin_layout Plain Layout
5271 (unless it occurs in a string).
5274 \begin_layout Standard
5275 Consider this line of C code:
5278 \begin_layout Standard
5279 \begin_inset Formula $\mathtt{things\underbrace{[\mathtt{x,\ y}]}_{1.\ [\ mode},\ get\_other\_things\underbrace{(\mathtt{a,\overbrace{"\mathtt{(all)}"}})}_{2.\ (\ mode}^{3.\ "\ mode}}$
5285 \begin_layout Standard
5286 Mode nesting prevents the close parenthesis in quote mode (part 3) from
5287 terminating the parenthesis mode (part 2).
5290 \begin_layout Standard
5291 Each language has a set of modes, the default mode being the null mode.
5292 Each mode can lead to other modes.
5295 \begin_layout Subsection
5296 Modes to included chunks
5299 \begin_layout Standard
5300 For instance, consider this chunk with
5301 \begin_inset Flex CharStyle:Code
5304 \begin_layout Plain Layout
5314 example-perl,language=perl
5317 \begin_layout Standard
5318 \begin_inset listings
5322 \begin_layout Plain Layout
5324 print "hello world $0
5334 \begin_layout Standard
5335 If it were included in a chunk with
5336 \begin_inset Flex CharStyle:Code
5339 \begin_layout Plain Layout
5349 example-sh,language=sh
5352 \begin_layout Standard
5353 \begin_inset listings
5357 \begin_layout Plain Layout
5361 chunkref{example-perl}>"
5369 \begin_layout Standard
5370 newfangle would need to generate output like this if it were to work:
5373 \begin_layout LyX-Code
5385 \begin_layout Standard
5386 See that the double quote
5387 \begin_inset Flex CharStyle:Code
5390 \begin_layout Plain Layout
5397 \begin_inset Flex CharStyle:Code
5400 \begin_layout Plain Layout
5406 in the regex have been quoted with a back-slash to protect them from shell
5410 \begin_layout Standard
5411 If that were then included in a chunk with
5412 \begin_inset Flex CharStyle:Code
5415 \begin_layout Plain Layout
5425 example-makefile,language=make
5428 \begin_layout Standard
5429 \begin_inset listings
5433 \begin_layout Plain Layout
5438 \begin_layout Plain Layout
5442 chunkref{example-sh}>
5450 \begin_layout Standard
5451 We would need the output to look like this --- note the $$:
5454 \begin_layout LyX-Code
5458 \begin_layout LyX-Code
5466 \begin_layout Standard
5467 In order to make this work, we need to define a mode-tracker supporting
5468 each language, that can detect the various quoting modes, and provide a
5469 transformation that must be applied to any included text so that included
5470 text will be interpreted correctly after any interpolation that it may
5471 be subject to at run-time.
5474 \begin_layout Standard
5475 For example, the sed transformation for text to be inserted into sh double-quote
5476 d strings would be something like:
5479 \begin_layout LyX-Code
5503 \begin_layout Standard
5505 \begin_inset Flex CharStyle:Code
5508 \begin_layout Plain Layout
5519 \begin_layout Standard
5520 \begin_inset Note Note
5523 \begin_layout Plain Layout
5524 I don't think this example is true
5529 The mode tracker must also track nested mode-changes, as in this
5530 \begin_inset Flex CharStyle:Code
5533 \begin_layout Plain Layout
5542 \begin_layout LyX-Code
5543 echo "hello `id \SpecialChar \ldots{}
5547 \begin_layout LyX-Code
5551 \begin_layout Plain Layout
5557 hphantom{echo "hello `id}
5565 \begin_layout Standard
5566 Any characters inserted at the point marked ↑ would need to be escaped,
5568 \begin_inset Flex CharStyle:Code
5571 \begin_layout Plain Layout
5578 First it would need escaping for the back-ticks `, and then for the double-quot
5582 \begin_layout Standard
5583 Escaping need not occur if the format and mode of the included chunk matches
5584 that of the including chunk.
5587 \begin_layout Standard
5588 As each chunk is output a new mode tracker for that language is initialized
5589 in it's normal state.
5590 As text is output for that chunk the output mode is tracked.
5591 When a new chunk is included, a transformation appropriate to that mode
5592 is selected and pushed onto a stack of transformations.
5593 Any text to be output is first passed through this stack of transformations.
5596 \begin_layout Standard
5597 It remains to consider if the chunk-include function should return it's
5598 generated text so that the caller can apply any transformations (and formatting
5599 ), or if it should apply the stack of transformations itself.
5602 \begin_layout Standard
5603 Note that the transformed text should have the property of not being able
5604 to change the mode in the current chunk.
5607 \begin_layout Standard
5608 \begin_inset Note Note
5611 \begin_layout Plain Layout
5612 Note chunk parameters should probably also be transformed
5620 \begin_layout Section
5621 Language Mode Definitions
5624 \begin_layout Standard
5625 All modes are stored in a single multi-dimensional hash.
5626 The first index is the language, and the second index is the mode-identifier.
5627 The third indexes are terminators, and optionally, submodes, and delimiters.
5630 \begin_layout Standard
5631 A useful set of mode definitions for a nameless general C-type language
5633 (Don't be confused by the double backslash escaping needed in awk.
5634 One set of escaping is for the string, and the second set of escaping is
5637 \begin_inset Note Note
5640 \begin_layout Plain Layout
5643 mode{}> command which will allow us to signify that a string is regex and
5644 thus newfangle will quote it for us.
5652 \begin_layout Standard
5653 Submodes are entered by the characters
5654 \begin_inset Flex CharStyle:Code
5657 \begin_layout Plain Layout
5666 \begin_inset Flex CharStyle:Code
5669 \begin_layout Plain Layout
5676 \begin_inset Flex CharStyle:Code
5679 \begin_layout Plain Layout
5686 \begin_inset Flex CharStyle:Code
5689 \begin_layout Plain Layout
5696 \begin_inset Flex CharStyle:Code
5699 \begin_layout Plain Layout
5706 \begin_inset Flex CharStyle:Code
5709 \begin_layout Plain Layout
5716 \begin_inset Flex CharStyle:Code
5719 \begin_layout Plain Layout
5729 common-mode-definitions,params=language
5732 \begin_layout Standard
5733 \begin_inset listings
5737 \begin_layout Plain Layout
5739 modes[${language}, "", "submodes" ]="
5765 \begin_layout Standard
5766 In the default mode, a comma surrounded by un-important white space is a
5767 delimiter of language items.
5770 \begin_layout Standard
5771 \begin_inset listings
5775 \begin_layout Plain Layout
5777 modes[${language}, "", "delimiters"]=" *, *";
5785 \begin_layout Standard
5786 and should pass this test:
5789 \begin_layout Standard
5790 \begin_inset Note Note
5793 \begin_layout Plain Layout
5794 Why do the tests run in
5795 \begin_inset Quotes eld
5799 \begin_inset Quotes erd
5803 \begin_inset Quotes eld
5807 \begin_inset Quotes erd
5819 test:mode-definitions
5822 \begin_layout Standard
5823 \begin_inset listings
5827 \begin_layout Plain Layout
5829 parse_chunk_args("c-like", "1,2,3", a, "");
5832 \begin_layout Plain Layout
5834 if (a[1] != "1") e++;
5837 \begin_layout Plain Layout
5839 if (a[2] != "2") e++;
5842 \begin_layout Plain Layout
5844 if (a[3] != "3") e++;
5847 \begin_layout Plain Layout
5849 if (length(a) != 3) e++;
5852 \begin_layout Plain Layout
5856 chunkref{pca-test.awk:summary}>
5859 \begin_layout Plain Layout
5863 \begin_layout Plain Layout
5865 parse_chunk_args("c-like", "joe, red", a, "");
5868 \begin_layout Plain Layout
5870 if (a[1] != "joe") e++;
5873 \begin_layout Plain Layout
5875 if (a[2] != "red") e++;
5878 \begin_layout Plain Layout
5880 if (length(a) != 2) e++;
5883 \begin_layout Plain Layout
5887 chunkref{pca-test.awk:summary}>
5890 \begin_layout Plain Layout
5894 \begin_layout Plain Layout
5896 parse_chunk_args("c-like", "${colour}", a, "");
5899 \begin_layout Plain Layout
5901 if (a[1] != "${colour}") e++;
5904 \begin_layout Plain Layout
5906 if (length(a) != 1) e++;
5909 \begin_layout Plain Layout
5913 chunkref{pca-test.awk:summary}>
5921 \begin_layout Standard
5922 Nested modes are identified by a backslash, a double or single quote, various
5923 bracket styles or a /* comment.
5926 \begin_layout Standard
5927 For each of these sub-modes modes we must also identify at a mode terminator,
5928 and any sub-modes or delimiters that may be entered
5932 \begin_layout Plain Layout
5933 Because we are using the sub-mode characters as the mode identifier it means
5934 we can't currently have a mode character dependant on it's context; i.e.
5936 \begin_inset Flex CharStyle:Code
5939 \begin_layout Plain Layout
5945 can't behave differently when it is inside
5946 \begin_inset Flex CharStyle:Code
5949 \begin_layout Plain Layout
5963 \begin_layout Subsection
5967 \begin_layout Standard
5968 The backslash mode has no submodes or delimiters, and is terminated by any
5970 Note that we are not so much interested in evaluating or interpolating
5971 content as we are in delineating content.
5972 It is no matter that a double backslash (
5973 \begin_inset Flex CharStyle:Code
5976 \begin_layout Plain Layout
5986 ) may represent a single backslash while a backslash-newline may represent
5987 white space, but it does matter that the newline in a backslash newline
5988 should not be able to terminate a C pre-processor statement; and so the
5989 newline will be consumed by the backslash however it is to be interpreted.
5993 common-mode-definitions
5996 \begin_layout Standard
5997 \begin_inset listings
6001 \begin_layout Plain Layout
6003 modes[${language}, "
6007 ", "terminators"]=".";
6015 \begin_layout Subsection
6019 \begin_layout Standard
6020 Common languages support two kinds of strings quoting, double quotes and
6025 mode:common-string,params=language;quote
6028 \begin_layout Standard
6029 In a string we have one special mode, which is the backslash.
6030 This may escape an embedded quote and prevent us thinking that it should
6031 terminate the string.
6035 \begin_layout Standard
6036 \begin_inset listings
6040 \begin_layout Plain Layout
6042 modes[${language}, ${quote}, "submodes" ]="
6058 \begin_layout Standard
6059 Otherwise, the string will be terminated by the same character that commenced
6063 \begin_layout Standard
6064 \begin_inset listings
6068 \begin_layout Plain Layout
6070 modes[${language}, ${quote}, "terminators"]=${quote};
6078 \begin_layout Standard
6079 In C type languages, certain escape sequences exist in strings.
6080 We need to define mechanism to enclode any chunks included in this mode
6081 using those escape sequences.
6082 These are expressed in two parts, s meaning search, and r meaning replace.
6085 \begin_layout Standard
6086 The first substitution is to replace a backslash with a double backslash.
6087 We do this first as other substitutions may introduce a backslash which
6088 we would not then want to escape again here.
6091 \begin_layout Standard
6092 Note: Backslashes need double-escaping in the search pattern but not in
6093 the replacement string, hence we are replacing a literal
6102 \begin_layout Standard
6103 \begin_inset listings
6107 \begin_layout Plain Layout
6109 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
6120 \begin_layout Plain Layout
6122 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
6138 \begin_layout Standard
6139 If the quote character occurs in the text, it should be preceded by a backslash,
6140 otherwise it would terminate the string unexpectedly.
6143 \begin_layout Standard
6144 \begin_inset listings
6148 \begin_layout Plain Layout
6150 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]=${quote};
6153 \begin_layout Plain Layout
6155 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
6167 \begin_layout Standard
6168 Any newlines in the string, must be replaced by
6169 \begin_inset Flex CharStyle:Code
6172 \begin_layout Plain Layout
6183 \begin_layout Standard
6184 \begin_inset listings
6188 \begin_layout Plain Layout
6190 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
6195 \begin_layout Plain Layout
6197 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
6209 \begin_layout Standard
6210 For the common modes, we define this string handling for double and single
6215 common-mode-definitions,params=language
6218 \begin_layout Standard
6219 \begin_inset listings
6223 \begin_layout Plain Layout
6227 chunkref{mode:common-string}(${language}, "
6232 \begin_layout Plain Layout
6236 chunkref{mode:common-string}(${language}, "'")>
6244 \begin_layout Standard
6245 Working strings should pass this test:
6249 test:mode-definitions
6252 \begin_layout Standard
6253 \begin_inset listings
6257 \begin_layout Plain Layout
6259 parse_chunk_args("c-like", "say
6278 \begin_layout Plain Layout
6299 \begin_layout Plain Layout
6301 if (a[2] != "for me") e++;
6304 \begin_layout Plain Layout
6306 if (length(a) != 2) e++;
6309 \begin_layout Plain Layout
6313 chunkref{pca-test.awk:summary}>
6321 \begin_layout Subsection
6322 Parentheses, Braces and Brackets
6325 \begin_layout Standard
6326 Where quotes are closed by the same character, parentheses, brackets and
6327 braces are closed by an alternate character.
6331 mode:common-brackets,params=language;open;close
6334 \begin_layout Standard
6335 \begin_inset listings
6339 \begin_layout Plain Layout
6341 modes[${language}, ${open}, "submodes" ]="
6366 \begin_layout Plain Layout
6368 modes[${language}, ${open}, "delimiters"]=" *, *";
6371 \begin_layout Plain Layout
6373 modes[${language}, ${open}, "terminators"]=${close};
6381 \begin_layout Standard
6382 Note that the open is NOT a regex but the close token IS.
6384 \begin_inset Note Note
6387 \begin_layout Plain Layout
6388 When we can quote regex we won't have to put the slashes in here
6397 common-mode-definitions,params=language
6400 \begin_layout Standard
6401 \begin_inset listings
6405 \begin_layout Plain Layout
6409 chunkref{mode:common-brackets}(${language}, "{", "}")>
6412 \begin_layout Plain Layout
6416 chunkref{mode:common-brackets}(${language}, "[", "
6423 \begin_layout Plain Layout
6427 chunkref{mode:common-brackets}(${language}, "(", "
6439 \begin_layout Subsection
6440 Customizing Standard Modes
6444 mode:add-submode,params=language;mode;submode
6447 \begin_layout Standard
6448 \begin_inset listings
6452 \begin_layout Plain Layout
6454 modes[${language}, ${mode}, "submodes"] = modes[${language}, ${mode}, "submodes"
6464 mode:add-escapes,params=language;mode;search;replace
6467 \begin_layout Standard
6468 \begin_inset listings
6472 \begin_layout Plain Layout
6474 escapes[${language}, ${mode}, ++escapes[${language}, ${mode}], "s"]=${search};
6477 \begin_layout Plain Layout
6479 escapes[${language}, ${mode}, escapes[${language}, ${mode}], "r"]=${replace};
6487 \begin_layout Subsection
6491 \begin_layout Standard
6493 \begin_inset Flex CharStyle:Code
6496 \begin_layout Plain Layout
6503 \begin_inset Flex CharStyle:Code
6506 \begin_layout Plain Layout
6512 style comments to be added to any language:
6516 mode:multi-line-comments,params=language
6519 \begin_layout Standard
6520 \begin_inset listings
6524 \begin_layout Plain Layout
6528 chunkref{mode:add-submode}(${language}, "", "/
6535 \begin_layout Plain Layout
6537 modes[${language}, "/*", "terminators"]="
6550 mode:single-line-slash-comments,params=language
6553 \begin_layout Standard
6554 \begin_inset listings
6558 \begin_layout Plain Layout
6562 chunkref{mode:add-submode}(${language}, "", "//")>
6565 \begin_layout Plain Layout
6567 modes[${language}, "//", "terminators"]="
6572 \begin_layout Plain Layout
6576 chunkref{mode:add-escapes}(${language}, "//", "
6578 textbackslash{}n", "
6580 textbackslash{}n//")>
6588 \begin_layout Standard
6590 \begin_inset Flex CharStyle:Code
6593 \begin_layout Plain Layout
6599 style comments (as used in awk and shell scripts) in a similar manner.
6603 mode:add-hash-comments,params=language
6604 \begin_inset Note Note
6607 \begin_layout Plain Layout
6614 and have hacky work-arounds in the parser for now
6622 \begin_layout Standard
6623 \begin_inset listings
6627 \begin_layout Plain Layout
6631 chunkref{mode:add-submode}(${language}, "", "
6636 \begin_layout Plain Layout
6638 modes[${language}, "#", "terminators"]="
6643 \begin_layout Plain Layout
6647 chunkref{mode:add-escapes}(${language}, "
6651 textbackslash{}n", "
6663 \begin_layout Standard
6665 \begin_inset Flex CharStyle:Code
6668 \begin_layout Plain Layout
6674 denotes pre-processor directives which can be multi-line
6678 mode:add-hash-defines,params=language
6681 \begin_layout Standard
6682 \begin_inset listings
6686 \begin_layout Plain Layout
6690 chunkref{mode:add-submode}(${language}, "", "
6695 \begin_layout Plain Layout
6697 modes[${language}, "#", "submodes" ]="
6708 \begin_layout Plain Layout
6710 modes[${language}, "#", "terminators"]="
6715 \begin_layout Plain Layout
6719 chunkref{mode:add-escapes}(${language}, "
6723 textbackslash{}n", "
6742 mode:quote-dollar-escape,params=language;quote
6745 \begin_layout Standard
6746 \begin_inset listings
6750 \begin_layout Plain Layout
6752 escapes[${language}, ${quote}, ++escapes[${language}, ${quote}], "s"]="
6759 \begin_layout Plain Layout
6761 escapes[${language}, ${quote}, escapes[${language}, ${quote}], "r"]="
6773 \begin_layout Standard
6774 We can add these definitions to various languages
6781 \begin_layout Standard
6782 \begin_inset listings
6786 \begin_layout Plain Layout
6790 chunkref{common-mode-definitions}("c-like")>
6793 \begin_layout Plain Layout
6797 \begin_layout Plain Layout
6801 chunkref{common-mode-definitions}("c")>
6804 \begin_layout Plain Layout
6808 chunkref{mode:multi-line-comments}("c")>
6811 \begin_layout Plain Layout
6815 chunkref{mode:single-line-slash-comments}("c")>
6818 \begin_layout Plain Layout
6822 chunkref{mode:add-hash-defines}("c")>
6825 \begin_layout Plain Layout
6829 \begin_layout Plain Layout
6833 chunkref{common-mode-definitions}("awk")>
6836 \begin_layout Plain Layout
6840 chunkref{mode:add-hash-comments}("awk")>
6843 \begin_layout Plain Layout
6847 chunkref{mode:add-naked-regex}("awk")>
6855 \begin_layout Standard
6856 The awk definitions should allow a comment block like this:
6860 test:comment-quote,language=awk
6863 \begin_layout Standard
6864 \begin_inset listings
6868 \begin_layout Plain Layout
6872 chunkref{test:comment-text}>
6881 test:comment-text,language=
6884 \begin_layout Standard
6885 \begin_inset listings
6889 \begin_layout Plain Layout
6894 \begin_layout Plain Layout
6896 the quick brown fox to bring lemonade
6899 \begin_layout Plain Layout
6909 \begin_layout Standard
6910 to come out like this:
6914 test:comment-quote:result
6917 \begin_layout Standard
6918 \begin_inset listings
6922 \begin_layout Plain Layout
6924 # Comment: Now is the time for
6927 \begin_layout Plain Layout
6929 #the quick brown fox to bring lemonade
6932 \begin_layout Plain Layout
6942 \begin_layout Standard
6943 The C definition for such a block should have it come out like this:
6947 test:comment-quote:C-result
6950 \begin_layout Standard
6951 \begin_inset listings
6955 \begin_layout Plain Layout
6957 # Comment: Now is the time for
6962 \begin_layout Plain Layout
6964 the quick brown fox to bring lemonade
6969 \begin_layout Plain Layout
6979 \begin_layout Subsection
6983 \begin_layout Standard
6984 This pattern is in-complete, but meant to detect naked regular expressions
6985 in awk and perl; e.g.
6987 \begin_inset Flex CharStyle:Code
6990 \begin_layout Plain Layout
6996 , however required capabilities are not present.
6999 \begin_layout Standard
7000 Current it only detects regexes anchored with
7001 \begin_inset Flex CharStyle:Code
7004 \begin_layout Plain Layout
7010 as used in newfangle.
7013 \begin_layout Standard
7014 For full regex support, modes need to be named not after their starting
7015 character, but some other more fully qualified name.
7019 mode:add-naked-regex,params=language
7022 \begin_layout Standard
7023 \begin_inset listings
7027 \begin_layout Plain Layout
7031 chunkref{mode:add-submode}(${language}, "", "/
7040 \begin_layout Plain Layout
7042 modes[${language}, "/^", "terminators"]="/";
7050 \begin_layout Subsection
7058 \begin_layout Standard
7059 \begin_inset listings
7063 \begin_layout Plain Layout
7067 chunkref{common-mode-definitions}("perl")>
7070 \begin_layout Plain Layout
7074 chunkref{mode:multi-line-comments}("perl")>
7077 \begin_layout Plain Layout
7081 chunkref{mode:add-hash-comments}("perl")>
7089 \begin_layout Standard
7090 Still need to add add s/, submod /, terminate both with //
7093 \begin_layout Subsection
7101 \begin_layout Standard
7102 \begin_inset listings
7106 \begin_layout Plain Layout
7110 chunkref{common-mode-definitions}("sh")>
7113 \begin_layout Plain Layout
7117 chunkref{mode:common-string}("sh", "
7122 \begin_layout Plain Layout
7126 chunkref{mode:common-string}("sh", "'")>
7129 \begin_layout Plain Layout
7133 chunkref{mode:add-hash-comments}("sh")>
7136 \begin_layout Plain Layout
7140 chunkref{mode:quote-dollar-escape}("sh", "
7150 \begin_layout Section
7154 \begin_layout Standard
7155 Also, the parser must return any spare text at the end that has not been
7156 processed due to a mode terminator being found.
7160 test:mode-definitions
7163 \begin_layout Standard
7164 \begin_inset listings
7168 \begin_layout Plain Layout
7170 rest = parse_chunk_args("c-like", "1, 2, 3) spare", a, "(");
7173 \begin_layout Plain Layout
7178 \begin_layout Plain Layout
7183 \begin_layout Plain Layout
7188 \begin_layout Plain Layout
7190 if (length(a) != 3) e++;
7193 \begin_layout Plain Layout
7195 if (rest != " spare") e++;
7198 \begin_layout Plain Layout
7202 chunkref{pca-test.awk:summary}>
7210 \begin_layout Standard
7211 We must also be able to parse the example given earlier.
7215 test:mode-definitions
7218 \begin_layout Standard
7219 \begin_inset listings
7223 \begin_layout Plain Layout
7225 parse_chunk_args("c-like", "things[x, y], get_other_things(a,
7232 \begin_layout Plain Layout
7234 if (a[1] != "things[x, y]") e++;
7237 \begin_layout Plain Layout
7239 if (a[2] != "get_other_things(a,
7246 \begin_layout Plain Layout
7248 if (a[3] != "99") e++;
7251 \begin_layout Plain Layout
7253 if (length(a) != 3) e++;
7256 \begin_layout Plain Layout
7260 chunkref{pca-test.awk:summary}>
7268 \begin_layout Section
7269 A non-recursive mode tracker
7272 \begin_layout Subsection
7276 \begin_layout Standard
7277 The mode tracker holds its state in a stack based on a hash.
7278 This function, when passed an empty hash will intialize it.
7285 \begin_layout Standard
7286 \begin_inset listings
7290 \begin_layout Plain Layout
7292 function new_mode_tracker(context, language, mode) {
7295 \begin_layout Plain Layout
7300 \begin_layout Plain Layout
7302 context[0, "language"] = language;
7305 \begin_layout Plain Layout
7307 context[0, "mode"] = mode;
7310 \begin_layout Plain Layout
7320 \begin_layout Standard
7321 Because awk functions cannot return an array, we must create the array first
7322 and pass it in, so we have a newfangle macro to do this:
7326 new-mode-tracker,language=awk,params=context;language;mode
7329 \begin_layout Standard
7330 \begin_inset listings
7334 \begin_layout Plain Layout
7338 chunkref{awk-delete-array}(${context})>
7341 \begin_layout Plain Layout
7343 new_mode_tracker(${context}, ${language}, ${mode});
7351 \begin_layout Subsection
7355 \begin_layout Standard
7356 And for tracking modes, we dispatch to a mode-tracker action based on the
7361 mode_tracker,language=awk
7364 \begin_layout Standard
7365 \begin_inset listings
7369 \begin_layout Plain Layout
7371 function push_mode_tracker(context, language, mode,
7374 \begin_layout Plain Layout
7379 \begin_layout Plain Layout
7384 \begin_layout Plain Layout
7389 \begin_layout Plain Layout
7391 if (! ("" in context)) {
7394 \begin_layout Plain Layout
7398 chunkref{new-mode-tracker}(context, language, mode)>
7401 \begin_layout Plain Layout
7406 \begin_layout Plain Layout
7411 \begin_layout Plain Layout
7413 if (context[top, "language"] == language && mode=="") mode = context[top,
7417 \begin_layout Plain Layout
7422 \begin_layout Plain Layout
7424 context[top, "language"] = language;
7427 \begin_layout Plain Layout
7429 context[top, "mode"] = mode;
7432 \begin_layout Plain Layout
7437 \begin_layout Plain Layout
7442 \begin_layout Plain Layout
7452 \begin_layout Standard
7453 \begin_inset listings
7457 \begin_layout Plain Layout
7459 function dump_mode_tracker(context,
7462 \begin_layout Plain Layout
7467 \begin_layout Plain Layout
7472 \begin_layout Plain Layout
7474 for(c=0; c <= context[""]; c++) {
7477 \begin_layout Plain Layout
7481 n", c, context[c, "language"], context[c, "mode"]) > "/dev/stderr";
7484 \begin_layout Plain Layout
7486 for(d=1; ( (c, "values", d) in context); d++) {
7489 \begin_layout Plain Layout
7493 n", d, context[c, "values", d]) > "/dev/stderr";
7496 \begin_layout Plain Layout
7501 \begin_layout Plain Layout
7506 \begin_layout Plain Layout
7516 \begin_layout Standard
7517 \begin_inset listings
7521 \begin_layout Plain Layout
7523 function finalize_mode_tracker(context)
7526 \begin_layout Plain Layout
7531 \begin_layout Plain Layout
7533 if ( ("" in context) && context[""] != 0) return 0;
7536 \begin_layout Plain Layout
7541 \begin_layout Plain Layout
7551 \begin_layout Standard
7552 This implies that any chunk must be syntactically whole; for instance, this
7560 \begin_layout Standard
7561 \begin_inset listings
7565 \begin_layout Plain Layout
7570 \begin_layout Plain Layout
7574 chunkref{test:say-hello}>
7577 \begin_layout Plain Layout
7591 \begin_layout Standard
7592 \begin_inset listings
7596 \begin_layout Plain Layout
7606 \begin_layout Standard
7607 But this is not fine; the chunk
7608 \begin_inset Flex Chunkref
7611 \begin_layout Plain Layout
7617 is not properly cromulent.
7624 \begin_layout Standard
7625 \begin_inset listings
7629 \begin_layout Plain Layout
7634 \begin_layout Plain Layout
7638 chunkref{test:hidden-else}>
7641 \begin_layout Plain Layout
7655 \begin_layout Standard
7656 \begin_inset listings
7660 \begin_layout Plain Layout
7665 \begin_layout Plain Layout
7670 \begin_layout Plain Layout
7680 \begin_layout Standard
7681 These tests will check for correct behaviour:
7688 \begin_layout Standard
7689 \begin_inset listings
7693 \begin_layout Plain Layout
7695 echo Cromulence test
7698 \begin_layout Plain Layout
7700 passtest $NEWFANGLE -Rtest:whole-chunk $TEX_SRC &>/dev/null || ( echo "Whole
7701 chunk failed" && exit 1 )
7704 \begin_layout Plain Layout
7706 failtest $NEWFANGLE -Rtest:partial-chunk $TEX_SRC &>/dev/null || ( echo
7707 "Partial chunk failed" && exit 1 )
7715 \begin_layout Subsection
7719 \begin_layout Standard
7720 We must avoid recursion as a language construct because we intend to employ
7721 mode-tracking to track language mode of emitted code, and the code is emitted
7722 from a function which is itself recursive, so instead we implement psuedo-recur
7723 sion using our own stack based on a hash.
7730 \begin_layout Standard
7731 \begin_inset listings
7735 \begin_layout Plain Layout
7737 function mode_tracker(context, text, values,
7740 \begin_layout Plain Layout
7742 # optional parameters
7745 \begin_layout Plain Layout
7750 \begin_layout Plain Layout
7752 mode, submodes, language,
7755 \begin_layout Plain Layout
7757 cindex, c, a, part, item, name, result, new_values, new_mode,
7760 \begin_layout Plain Layout
7762 delimiters, terminators)
7765 \begin_layout Plain Layout
7775 \begin_layout Standard
7776 We could be re-commencing with a valid context, so we need to setup the
7777 state according to the last context.
7780 \begin_layout Standard
7781 \begin_inset listings
7785 \begin_layout Plain Layout
7787 cindex = context[""] + 0;
7790 \begin_layout Plain Layout
7792 mode = context[cindex, "mode"];
7795 \begin_layout Plain Layout
7797 language = context[cindex, "language" ];
7805 \begin_layout Standard
7806 First we construct a single large regex combining the possible sub-modes
7807 for the current mode along with the terminators for the current mode.
7811 parse_chunk_args-reset-modes
7814 \begin_layout Standard
7815 \begin_inset listings
7819 \begin_layout Plain Layout
7821 submodes=modes[language, mode, "submodes"];
7824 \begin_layout Plain Layout
7828 \begin_layout Plain Layout
7830 if ((language, mode, "delimiters") in modes) {
7833 \begin_layout Plain Layout
7835 delimiters = modes[language, mode, "delimiters"];
7838 \begin_layout Plain Layout
7840 if (length(submodes)>0) submodes = submodes "|";
7843 \begin_layout Plain Layout
7845 submodes=submodes delimiters;
7848 \begin_layout Plain Layout
7850 } else delimiters="";
7853 \begin_layout Plain Layout
7855 if ((language, mode, "terminators") in modes) {
7858 \begin_layout Plain Layout
7860 terminators = modes[language, mode, "terminators"];
7863 \begin_layout Plain Layout
7865 if (length(submodes)>0) submodes = submodes "|";
7868 \begin_layout Plain Layout
7870 submodes=submodes terminators;
7873 \begin_layout Plain Layout
7875 } else terminators="";
7883 \begin_layout Standard
7884 If we don't find anything to match on --- probably because the language
7885 is not supported --- then we return the entire text without matching anything.
7888 \begin_layout Standard
7889 \begin_inset listings
7893 \begin_layout Plain Layout
7895 if (! length(submodes)) return text;
7907 \begin_layout Standard
7908 \begin_inset listings
7912 \begin_layout Plain Layout
7916 chunkref{parse_chunk_args-reset-modes}>
7924 \begin_layout Standard
7925 We then iterate the text (until there is none left) looking for sub-modes
7926 or terminators in the regex.
7929 \begin_layout Standard
7930 \begin_inset listings
7934 \begin_layout Plain Layout
7936 while((cindex >= 0) && length(text)) {
7939 \begin_layout Plain Layout
7941 if (match(text, "(" submodes ")", a)) {
7949 \begin_layout Standard
7950 A bug that creeps in regularly during development is bad regexes of zero
7951 length which result in an infinite loop (as no text is consumed), so I
7952 catch that right away with this test.
7955 \begin_layout Standard
7956 \begin_inset listings
7960 \begin_layout Plain Layout
7965 \begin_layout Plain Layout
7967 error(sprintf("Internal error, matched zero length submode, should
7968 be impossible - likely regex computation error
7975 \begin_layout Plain Layout
7983 n", language, mode, submodes));
7986 \begin_layout Plain Layout
7996 \begin_layout Standard
7997 \begin_inset Flex CharStyle:Code
8000 \begin_layout Plain Layout
8006 is defined as the text up to the sub-mode or terminator, and this is appended
8008 \begin_inset Flex CharStyle:Code
8011 \begin_layout Plain Layout
8017 --- which is the current text being gathered.
8018 If a mode has a delimiter, then item is reset each time a delimiter is
8022 \begin_layout Standard
8023 \begin_inset Formula $\mathtt{\overbrace{"\overbrace{hello}^{item},\ \overbrace{there}^{item}"}^{item},\ \overbrace{he\ said.}^{item}}$
8029 \begin_layout Standard
8030 \begin_inset listings
8034 \begin_layout Plain Layout
8036 part = substr(text, 1, RSTART -1);
8039 \begin_layout Plain Layout
8049 \begin_layout Standard
8050 We must now determine what was matched.
8051 If it was a terminator, then we must restore the previous mode.
8054 \begin_layout Standard
8055 \begin_inset listings
8059 \begin_layout Plain Layout
8061 if (match(a[1], "^" terminators "$")) {
8064 \begin_layout Plain Layout
8066 #printf("%2d EXIT MODE [%s] by [%s] [%s]
8068 n", cindex, mode, a[1], text) > "/dev/stderr"
8071 \begin_layout Plain Layout
8073 context[cindex, "values", ++context[cindex, "values"]] = item;
8076 \begin_layout Plain Layout
8078 delete context[cindex];
8081 \begin_layout Plain Layout
8083 context[""] = --cindex;
8086 \begin_layout Plain Layout
8091 \begin_layout Plain Layout
8093 mode = context[cindex, "mode"];
8096 \begin_layout Plain Layout
8098 language = context[cindex, "language"];
8101 \begin_layout Plain Layout
8105 chunkref{parse_chunk_args-reset-modes}>
8108 \begin_layout Plain Layout
8113 \begin_layout Plain Layout
8118 \begin_layout Plain Layout
8120 text = substr(text, 1 + length(part) + length(a[1]));
8123 \begin_layout Plain Layout
8133 \begin_layout Standard
8134 If a delimiter was matched, then we must store the current item in the parsed
8135 values array, and reset the item.
8138 \begin_layout Standard
8139 \begin_inset listings
8143 \begin_layout Plain Layout
8145 else if (match(a[1], "^" delimiters "$")) {
8148 \begin_layout Plain Layout
8153 \begin_layout Plain Layout
8155 context[cindex, "values", ++context[cindex, "values"]] = item;
8158 \begin_layout Plain Layout
8163 \begin_layout Plain Layout
8168 \begin_layout Plain Layout
8173 \begin_layout Plain Layout
8178 \begin_layout Plain Layout
8180 text = substr(text, 1 + length(part) + length(a[1]));
8183 \begin_layout Plain Layout
8193 \begin_layout Standard
8194 otherwise, if a new submode is detected (all submodes have terminators),
8195 we must create a nested parse context until we find the terminator for
8199 \begin_layout Standard
8200 \begin_inset listings
8204 \begin_layout Plain Layout
8206 else if ((language, a[1], "terminators") in modes) {
8209 \begin_layout Plain Layout
8211 #check if new_mode is defined
8214 \begin_layout Plain Layout
8219 \begin_layout Plain Layout
8221 #printf("%2d ENTER MODE [%s] in [%s]
8223 n", cindex, a[1], text) > "/dev/stderr"
8226 \begin_layout Plain Layout
8228 text = substr(text, 1 + length(part) + length(a[1]));
8231 \begin_layout Plain Layout
8233 context[""] = ++cindex;
8236 \begin_layout Plain Layout
8238 context[cindex, "mode"] = a[1];
8241 \begin_layout Plain Layout
8243 context[cindex, "language"] = language;
8246 \begin_layout Plain Layout
8251 \begin_layout Plain Layout
8255 chunkref{parse_chunk_args-reset-modes}>
8258 \begin_layout Plain Layout
8263 \begin_layout Plain Layout
8265 error(sprintf("Submode '%s' set unknown mode in text: %s
8267 nLanguage %s Mode %s
8269 n", a[1], text, language, mode));
8272 \begin_layout Plain Layout
8274 text = substr(text, 1 + length(part) + length(a[1]));
8277 \begin_layout Plain Layout
8282 \begin_layout Plain Layout
8292 \begin_layout Standard
8293 In the final case, we parsed to the end of the string.
8294 If the string was entire, then we should have no nested mode context, but
8295 if the string was just a fragment we may have a mode context which must
8296 be preserved for the next fragment.
8297 Todo: Consideration ought to be given if sub-mode strings are split over
8299 \begin_inset Note Note
8302 \begin_layout Plain Layout
8303 Consideration ought to be given if sub-mode strings are split over two fragments.
8311 \begin_layout Standard
8312 \begin_inset listings
8316 \begin_layout Plain Layout
8321 \begin_layout Plain Layout
8323 context[cindex, "values", ++context[cindex, "values"]] = item text;
8326 \begin_layout Plain Layout
8331 \begin_layout Plain Layout
8336 \begin_layout Plain Layout
8341 \begin_layout Plain Layout
8346 \begin_layout Plain Layout
8350 \begin_layout Plain Layout
8352 context["item"] = item;
8355 \begin_layout Plain Layout
8359 \begin_layout Plain Layout
8361 if (length(item)) context[cindex, "values", ++context[cindex, "values"]]
8365 \begin_layout Plain Layout
8370 \begin_layout Plain Layout
8380 \begin_layout Subsubsection
8384 \begin_layout Standard
8385 All the mode tracker chunks are referred to here:
8392 \begin_layout Standard
8393 \begin_inset listings
8397 \begin_layout Plain Layout
8401 chunkref{new_mode_tracker()}>
8404 \begin_layout Plain Layout
8408 chunkref{mode_tracker()}>
8416 \begin_layout Subsubsection
8420 \begin_layout Standard
8421 We can test this function like this:
8425 pca-test.awk,language=awk
8428 \begin_layout Standard
8429 \begin_inset listings
8433 \begin_layout Plain Layout
8440 \begin_layout Plain Layout
8444 chunkref{mode-tracker}>
8447 \begin_layout Plain Layout
8451 chunkref{parse_chunk_args()}>
8454 \begin_layout Plain Layout
8459 \begin_layout Plain Layout
8464 \begin_layout Plain Layout
8468 chunkref{mode-definitions}>
8471 \begin_layout Plain Layout
8475 \begin_layout Plain Layout
8479 chunkref{test:mode-definitions}>
8482 \begin_layout Plain Layout
8493 pca-test.awk:summary,language=awk
8496 \begin_layout Standard
8497 \begin_inset listings
8501 \begin_layout Plain Layout
8506 \begin_layout Plain Layout
8511 \begin_layout Plain Layout
8516 \begin_layout Plain Layout
8518 print "a[" b "] => " a[b];
8521 \begin_layout Plain Layout
8526 \begin_layout Plain Layout
8531 \begin_layout Plain Layout
8536 \begin_layout Plain Layout
8541 \begin_layout Plain Layout
8546 \begin_layout Plain Layout
8556 \begin_layout Standard
8557 which should give this output:
8561 pca-test.awk-results,language=
8564 \begin_layout Standard
8565 \begin_inset listings
8569 \begin_layout Plain Layout
8571 a[foo.quux.quirk] =>
8574 \begin_layout Plain Layout
8576 a[foo.quux.a] => fleeg
8579 \begin_layout Plain Layout
8584 \begin_layout Plain Layout
8589 \begin_layout Plain Layout
8599 \begin_layout Section
8600 Escaping and Quoting
8603 \begin_layout Standard
8604 Each nested mode can optionally define a set of transforms to be applied
8605 to any text that is included from another language.
8608 \begin_layout Standard
8609 This code can perform transforms
8613 mode_tracker,language=awk
8616 \begin_layout Standard
8617 \begin_inset listings
8621 \begin_layout Plain Layout
8623 function transform_escape(s, r, text,
8626 \begin_layout Plain Layout
8631 \begin_layout Plain Layout
8636 \begin_layout Plain Layout
8641 \begin_layout Plain Layout
8646 \begin_layout Plain Layout
8651 \begin_layout Plain Layout
8653 for(c=1; c <= max && (c in s); c++) {
8656 \begin_layout Plain Layout
8658 gsub(s[c], r[c], text);
8661 \begin_layout Plain Layout
8666 \begin_layout Plain Layout
8671 \begin_layout Plain Layout
8681 \begin_layout Standard
8682 This function must append from index
8683 \begin_inset Flex CharStyle:Code
8686 \begin_layout Plain Layout
8692 onwards, and escape transforms from the supplied context, and return c
8693 + number of new transforms.
8696 \begin_layout Standard
8697 \begin_inset listings
8701 \begin_layout Plain Layout
8703 function mode_escaper(context, s, r, src,
8706 \begin_layout Plain Layout
8711 \begin_layout Plain Layout
8716 \begin_layout Plain Layout
8718 for(c = context[""]; c >= 0; c--) {
8721 \begin_layout Plain Layout
8723 if ( (context[c, "language"], context[c, "mode"]) in escapes) {
8726 \begin_layout Plain Layout
8728 cpl = escapes[context[c, "language"], context[c, "mode"]];
8731 \begin_layout Plain Layout
8733 for (cp = 1; cp <= cpl; cp ++) {
8736 \begin_layout Plain Layout
8741 \begin_layout Plain Layout
8743 s[src] = escapes[context[c, "language"], context[c, "mode"], cp, "s"];
8746 \begin_layout Plain Layout
8748 r[src] = escapes[context[c, "language"], context[c, "mode"], cp, "r"];
8751 \begin_layout Plain Layout
8756 \begin_layout Plain Layout
8761 \begin_layout Plain Layout
8766 \begin_layout Plain Layout
8771 \begin_layout Plain Layout
8776 \begin_layout Plain Layout
8778 function dump_escaper(c, s, r, cc) {
8781 \begin_layout Plain Layout
8783 for(cc=1; cc<=c; cc++) {
8786 \begin_layout Plain Layout
8788 printf("%2d s[%s] r[%s]
8790 n", cc, s[cc], r[cc]) > "/dev/stderr"
8793 \begin_layout Plain Layout
8798 \begin_layout Plain Layout
8809 test:escapes,language=sh
8812 \begin_layout Standard
8813 \begin_inset listings
8817 \begin_layout Plain Layout
8822 \begin_layout Plain Layout
8824 passtest $NEWFANGLE -Rtest:comment-quote $TEX_SRC &>/dev/null || ( echo
8825 "Comment-quote failed" && exit 1 )
8833 \begin_layout Chapter
8837 \begin_layout Standard
8838 Newfangle recognizes noweb chunks, but as we also want better LaTeX integration
8839 we will recognize any of these:
8842 \begin_layout Itemize
8843 notangle chunks matching the pattern
8844 \begin_inset Flex CharStyle:Code
8847 \begin_layout Plain Layout
8849 \begin_inset space \hspace*{}
8854 \begin_inset space \hspace*{}
8866 \begin_layout Itemize
8867 a chunks beginning with
8868 \begin_inset Flex CharStyle:Code
8871 \begin_layout Plain Layout
8881 Chunk{\SpecialChar \ldots{}
8882 } on the previous line
8885 \begin_layout Itemize
8886 an older form I have used, beginning with
8887 \begin_inset Flex CharStyle:Code
8890 \begin_layout Plain Layout
8893 begin{Chunk}[options]
8898 --- also more suitable for plain LaTeX users
8902 \begin_layout Plain Layout
8903 Is there such a thing as plain LaTeX?
8911 \begin_layout Section
8915 \begin_layout Standard
8917 \begin_inset Flex CharStyle:Code
8920 \begin_layout Plain Layout
8926 is used to signify that we are processing a code chunk and not document.
8927 In such a state, input lines will be assigned to the current chunk; otherwise
8931 \begin_layout Subsection
8935 \begin_layout Standard
8936 Our current scheme is to recognize the new lstlisting chunks, but these
8937 may be preceded by a
8938 \begin_inset Flex CharStyle:Code
8941 \begin_layout Plain Layout
8949 command which in LyX is a more convenient way to pass the chunk name to
8951 \begin_inset Flex CharStyle:Code
8954 \begin_layout Plain Layout
8962 command, and a more visible way to specify other
8963 \begin_inset Flex CharStyle:Code
8966 \begin_layout Plain Layout
8975 \begin_layout Standard
8976 The arguments to the
8977 \begin_inset Flex CharStyle:Code
8980 \begin_layout Plain Layout
8988 command are a name, and then a comma-seperated list of key-value pairs
8990 \begin_inset Flex CharStyle:Code
8993 \begin_layout Plain Layout
9002 (In fact within the LaTeX
9003 \begin_inset Flex CharStyle:Code
9006 \begin_layout Plain Layout
9015 \begin_inset CommandInset ref
9017 reference "sub:The-chunk-command"
9022 \begin_inset Flex CharStyle:Code
9025 \begin_layout Plain Layout
9031 is prefixed to the argument which is then literally passed to
9032 \begin_inset Flex CharStyle:Code
9035 \begin_layout Plain Layout
9047 recognize-chunk,language=awk
9050 \begin_layout Standard
9051 \begin_inset listings
9055 \begin_layout Plain Layout
9064 \begin_layout Plain Layout
9074 Chunk{ *([^ ,}]*),?(.*)}", line)) {
9077 \begin_layout Plain Layout
9079 next_chunk_name = line[1];
9082 \begin_layout Plain Layout
9084 get_chunk_args(line[2], next_chunk_args);
9087 \begin_layout Plain Layout
9092 \begin_layout Plain Layout
9097 \begin_layout Plain Layout
9107 \begin_layout Standard
9108 We also make a basic attempt to parse the name out of the
9109 \begin_inset Flex CharStyle:Code
9112 \begin_layout Plain Layout
9116 \begin_inset space \hspace{}
9125 text, otherwise we fall back to the name found in the previous chunk command.
9126 This attempt is very basic and doesn't support commas or spaces or square
9127 brackets as part of the chunkname.
9129 \begin_inset Flex CharStyle:Code
9132 \begin_layout Plain Layout
9140 which is convenient for some users
9144 \begin_layout Plain Layout
9145 but not yet supported in the LaTeX macros
9151 \begin_inset Note Note
9154 \begin_layout Plain Layout
9163 \begin_layout Standard
9164 \begin_inset listings
9168 \begin_layout Plain Layout
9181 \begin_layout Plain Layout
9183 if (match($0, "}.*[[,] *name= *{? *([^], }]*)", line)) {
9186 \begin_layout Plain Layout
9191 \begin_layout Plain Layout
9196 \begin_layout Plain Layout
9198 new_chunk(next_chunk_name, next_chunk_args);
9201 \begin_layout Plain Layout
9206 \begin_layout Plain Layout
9211 \begin_layout Plain Layout
9216 \begin_layout Plain Layout
9226 \begin_layout Subsection
9230 \begin_layout Standard
9231 We recognize notangle style chunks too:
9235 recognize-chunk,language=awk
9238 \begin_layout Standard
9239 \begin_inset listings
9243 \begin_layout Plain Layout
9248 \begin_layout Plain Layout
9250 if (match($0, "^[<]<(.*)[>]>= *$", line)) {
9253 \begin_layout Plain Layout
9258 \begin_layout Plain Layout
9263 \begin_layout Plain Layout
9268 \begin_layout Plain Layout
9273 \begin_layout Plain Layout
9278 \begin_layout Plain Layout
9288 \begin_layout Section
9292 \begin_layout Standard
9293 Likewise, we need to recognize when a chunk ends.
9296 \begin_layout Subsection
9300 \begin_layout Standard
9302 \begin_inset Flex CharStyle:Code
9305 \begin_layout Plain Layout
9312 \begin_inset Flex CharStyle:Code
9315 \begin_layout Plain Layout
9321 is surrounded by square brackets so that when this document is processed,
9322 this chunk doesn't terminate early when the lstlistings package recognizes
9323 it's own end-string!
9324 \begin_inset Note Greyedout
9327 \begin_layout Plain Layout
9328 This doesn't make sense as the regex is anchored with ^, which this line
9329 does not begin with!
9335 \begin_inset Note Note
9338 \begin_layout Plain Layout
9351 \begin_layout Standard
9352 \begin_inset listings
9356 \begin_layout Plain Layout
9369 \begin_layout Plain Layout
9374 \begin_layout Plain Layout
9379 \begin_layout Plain Layout
9384 \begin_layout Plain Layout
9394 \begin_layout Subsection
9402 \begin_layout Standard
9403 \begin_inset listings
9407 \begin_layout Plain Layout
9412 \begin_layout Plain Layout
9417 \begin_layout Plain Layout
9422 \begin_layout Plain Layout
9432 \begin_layout Standard
9433 All other recognizers are only of effect if we are chunking; there's no
9434 point in looking at lines if they aren't part of a chunk, so we just ignore
9435 them as efficiently as we can.
9442 \begin_layout Standard
9443 \begin_inset listings
9447 \begin_layout Plain Layout
9449 ! chunking { next; }
9457 \begin_layout Section
9461 \begin_layout Standard
9462 Chunk contents are any lines read while
9463 \begin_inset Flex CharStyle:Code
9466 \begin_layout Plain Layout
9473 Some chunk contents are special in that they refer to other chunks, and
9474 will be replaced by the contents of these chunks when the file is generated.
9477 \begin_layout Standard
9478 \begin_inset CommandInset label
9480 name "sub:ORS-chunk-text"
9484 We add the output record separator
9485 \begin_inset Flex CharStyle:Code
9488 \begin_layout Plain Layout
9494 to the line now, because we will set
9495 \begin_inset Flex CharStyle:Code
9498 \begin_layout Plain Layout
9504 to the empty string when we generate the output
9508 \begin_layout Plain Layout
9509 So that we can print partial lines using
9510 \begin_inset Flex CharStyle:Code
9513 \begin_layout Plain Layout
9520 \begin_inset Flex CharStyle:Code
9523 \begin_layout Plain Layout
9541 \begin_layout Standard
9542 \begin_inset listings
9546 \begin_layout Plain Layout
9548 length(active_chunk) {
9551 \begin_layout Plain Layout
9555 chunkref{process-chunk-tabs}>
9558 \begin_layout Plain Layout
9562 chunkref{process-chunk}>
9565 \begin_layout Plain Layout
9575 \begin_layout Standard
9576 If a chunk just consisted of plain text, we could handle the chunk like
9581 process-chunk-simple
9584 \begin_layout Standard
9585 \begin_inset listings
9589 \begin_layout Plain Layout
9591 chunk_line(active_chunk, $0 ORS);
9599 \begin_layout Standard
9600 but in fact a chunk can include references to other chunks.
9601 Chunk includes are traditionally written as
9602 \begin_inset Flex CharStyle:Code
9605 \begin_layout Plain Layout
9611 , but we support other variations.
9614 \begin_layout Standard
9615 However, we also process tabs at this point, a tab at input can be replaced
9616 by a number of spaces defined by the
9617 \begin_inset Flex CharStyle:Code
9620 \begin_layout Plain Layout
9626 variable, set by the
9627 \begin_inset Flex CharStyle:Code
9630 \begin_layout Plain Layout
9637 Of course this is poor tab behaviour, we should probably have the option
9638 to use proper counted tab-stops and process this on output.
9645 \begin_layout Standard
9646 \begin_inset listings
9650 \begin_layout Plain Layout
9655 \begin_layout Plain Layout
9662 \begin_layout Plain Layout
9672 \begin_layout Subsection
9673 \begin_inset CommandInset label
9675 name "sub:lstlistings-includes"
9682 \begin_layout Standard
9684 \begin_inset Flex CharStyle:Code
9687 \begin_layout Plain Layout
9690 lstset{escapeinside={=<}{>}}
9695 is set, then we can use
9696 \begin_inset Flex CharStyle:Code
9699 \begin_layout Plain Layout
9703 \begin_inset space \hspace{}
9714 \begin_inset Flex CharStyle:Code
9717 \begin_layout Plain Layout
9726 \begin_layout Enumerate
9727 it is a better mnemonic than
9728 \begin_inset Flex CharStyle:Code
9731 \begin_layout Plain Layout
9737 in that the = sign signifies equivalent or substitutability,
9740 \begin_layout Enumerate
9741 and because =< is not valid in C or in any language I can think of
9744 \begin_layout Enumerate
9745 and also because lstlistings doesn't like
9746 \begin_inset Flex CharStyle:Code
9749 \begin_layout Plain Layout
9755 as an end delimiter for the
9759 escape, so we must make do with a single
9760 \begin_inset Flex CharStyle:Code
9763 \begin_layout Plain Layout
9769 , which is better matched by
9770 \begin_inset Flex CharStyle:Code
9773 \begin_layout Plain Layout
9780 \begin_inset Flex CharStyle:Code
9783 \begin_layout Plain Layout
9792 \begin_layout Standard
9794 \begin_inset Note Note
9797 \begin_layout Plain Layout
9804 \begin_inset Flex CharStyle:Code
9807 \begin_layout Plain Layout
9808 =<\SpecialChar \ldots{}
9814 that we use re-enters a LaTeX parsing mode in which some characters are
9817 \begin_inset Flex CharStyle:Code
9820 \begin_layout Plain Layout
9828 , and so these cause trouble if used in arguments to
9829 \begin_inset Flex CharStyle:Code
9832 \begin_layout Plain Layout
9841 At some point I must fix the LaTeX command
9842 \begin_inset Flex CharStyle:Code
9845 \begin_layout Plain Layout
9853 so that it can accept these literally, but until then, when writing chunkref
9854 argumemts that need these characters, I must use the forms
9855 \begin_inset Flex CharStyle:Code
9858 \begin_layout Plain Layout
9867 \begin_inset Flex CharStyle:Code
9870 \begin_layout Plain Layout
9878 ; so I also define a hacky chunk
9879 \begin_inset Flex CharStyle:Code
9882 \begin_layout Plain Layout
9888 whose purpose it is to remove these from any arguments parsed by newfangle,
9889 and used further on.
9896 \begin_layout Standard
9897 \begin_inset listings
9901 \begin_layout Plain Layout
9906 \begin_layout Plain Layout
9919 \begin_layout Plain Layout
9936 \begin_layout Plain Layout
9958 \begin_layout Standard
9959 As each chunk line may contain more than one chunk include, we will split
9960 out chunk includes in an iterative fashion
9964 \begin_layout Plain Layout
9965 Contrary to our use of
9966 \begin_inset Flex CharStyle:Code
9969 \begin_layout Plain Layout
9975 when substituting parameters in chapter
9976 \begin_inset CommandInset ref
9978 reference "Here-we-split"
9990 \begin_layout Standard
9991 First, as long as the chunk contains a
9992 \begin_inset Flex CharStyle:Code
9995 \begin_layout Plain Layout
10003 command we take as much as we can up to the first
10004 \begin_inset Flex CharStyle:Code
10007 \begin_layout Plain Layout
10018 \begin_layout Chunk
10022 \begin_layout Standard
10023 \begin_inset listings
10027 \begin_layout Plain Layout
10032 \begin_layout Plain Layout
10037 \begin_layout Plain Layout
10042 \begin_layout Plain Layout
10052 chunkref{([^}>]*)}(
10060 )|)>|<<([a-zA-Z_][-a-zA-Z0-9_]*)>>)",
10063 \begin_layout Plain Layout
10070 \begin_layout Plain Layout
10075 \begin_layout Plain Layout
10077 chunklet = substr(chunk, 1, RSTART - 1);
10085 \begin_layout Standard
10086 We keep track of the indent count, by counting the number of literal characters
10088 We can then preserve this indent on each output line when multi-line chunks
10092 \begin_layout Standard
10093 We then process this first part literal text, and set the chunk which is
10094 still to be processed to be the text after the
10095 \begin_inset Flex CharStyle:Code
10098 \begin_layout Plain Layout
10106 command, which we will process next as we continue around the loop.
10109 \begin_layout Standard
10110 \begin_inset listings
10114 \begin_layout Plain Layout
10116 indent += length(chunklet);
10119 \begin_layout Plain Layout
10121 chunk_line(active_chunk, chunklet);
10124 \begin_layout Plain Layout
10126 chunk = substr(chunk, RSTART + RLENGTH);
10134 \begin_layout Standard
10135 We then consider the type of chunk command we have found, whether it is
10136 the newfangle style command beginning with
10137 \begin_inset Flex CharStyle:Code
10140 \begin_layout Plain Layout
10146 or the older notangle style beginning with
10147 \begin_inset Flex CharStyle:Code
10150 \begin_layout Plain Layout
10160 \begin_layout Standard
10161 Newfangle chunks may have parameters contained within square brackets.
10162 These will be matched in
10163 \begin_inset Flex CharStyle:Code
10166 \begin_layout Plain Layout
10172 and are considered at this stage of processing to be part of the name of
10173 the chunk to be included.
10176 \begin_layout Standard
10177 \begin_inset listings
10181 \begin_layout Plain Layout
10183 if (substr(line[1], 1, 1) == "=") {
10186 \begin_layout Plain Layout
10188 # chunk name up to }
10191 \begin_layout Plain Layout
10195 chunkref{delatex}(line[3])>
10198 \begin_layout Plain Layout
10200 chunk_include(active_chunk, line[2] line[3], indent);
10203 \begin_layout Plain Layout
10205 } else if (substr(line[1], 1, 1) == "<") {
10208 \begin_layout Plain Layout
10210 chunk_include(active_chunk, line[4], indent);
10213 \begin_layout Plain Layout
10218 \begin_layout Plain Layout
10220 error("Unknown chunk fragment: " line[1]);
10223 \begin_layout Plain Layout
10233 \begin_layout Standard
10234 The loop will continue until there are no more chunkref statements in the
10235 text, at which point we process the final part of the chunk.
10238 \begin_layout Standard
10239 \begin_inset listings
10243 \begin_layout Plain Layout
10248 \begin_layout Plain Layout
10250 chunk_line(active_chunk, chunk);
10258 \begin_layout Standard
10259 \begin_inset CommandInset label
10261 name "lone-newline"
10265 We add the newline character as a chunklet on it's own, to make it easier
10266 to detect new lines and thus manage indentation when processing the output.
10269 \begin_layout Standard
10270 \begin_inset listings
10274 \begin_layout Plain Layout
10276 chunk_line(active_chunk, "
10286 \begin_layout Standard
10287 We will also permit a chunk-part number to follow in square brackets, so
10289 \begin_inset Flex CharStyle:Code
10292 \begin_layout Plain Layout
10295 chunkref{chunk-name[1]}>
10300 will refer to the first part only.
10301 This can make it easy to include a C function prototype in a header file,
10302 if the first part of the chunk is just the function prototype without the
10303 trailing semi-colon.
10304 The header file would include the prototype with the trailing semi-colon,
10308 \begin_layout LyX-Code
10311 chunkref{chunk-name[1]}>;
10314 \begin_layout Standard
10315 This is handled in section
10316 \begin_inset CommandInset ref
10318 reference "sub:Chunk-parts"
10325 \begin_layout Standard
10326 We should perhaps introduce a notion of language specific chunk options;
10327 so that perhaps we could specify:
10330 \begin_layout LyX-Code
10333 chunkref{chunk-name[function-declaration]}>;
10336 \begin_layout Standard
10337 which applies a transform
10338 \begin_inset Flex CharStyle:Code
10341 \begin_layout Plain Layout
10342 function-declaration
10347 to the chunk --- which in this case would extract a function prototype
10349 \begin_inset Note Note
10352 \begin_layout Plain Layout
10361 \begin_layout Chapter
10365 \begin_layout Standard
10366 At the start, first we set the default options.
10369 \begin_layout Chunk
10373 \begin_layout Standard
10374 \begin_inset listings
10378 \begin_layout Plain Layout
10383 \begin_layout Plain Layout
10388 \begin_layout Plain Layout
10393 \begin_layout Plain Layout
10398 \begin_layout Plain Layout
10408 \begin_layout Standard
10409 Then we use getopt the standard way, and null out ARGV afterwards in the
10410 normal AWK fashion.
10413 \begin_layout Chunk
10417 \begin_layout Standard
10418 \begin_inset listings
10422 \begin_layout Plain Layout
10424 Optind = 1 # skip ARGV[0]
10427 \begin_layout Plain Layout
10429 while(getopt(ARGC, ARGV, "R:LdT:hr")!=-1) {
10432 \begin_layout Plain Layout
10436 chunkref{handle-options}>
10439 \begin_layout Plain Layout
10444 \begin_layout Plain Layout
10446 for (i=1; i<Optind; i++) { ARGV[i]=""; }
10454 \begin_layout Standard
10455 This is how we handle our options:
10458 \begin_layout Chunk
10462 \begin_layout Standard
10463 \begin_inset listings
10467 \begin_layout Plain Layout
10469 if (Optopt == "R") root = Optarg;
10472 \begin_layout Plain Layout
10474 else if (Optopt == "r") root="";
10477 \begin_layout Plain Layout
10479 else if (Optopt == "L") linenos = 1;
10482 \begin_layout Plain Layout
10484 else if (Optopt == "d") debug = 1;
10487 \begin_layout Plain Layout
10489 else if (Optopt == "T") tabs = indent_string(Optarg+0);
10492 \begin_layout Plain Layout
10494 else if (Optopt == "h") help();
10497 \begin_layout Plain Layout
10499 else if (Optopt == "?") help();
10507 \begin_layout Standard
10508 We do all of this at the beginning of the program
10511 \begin_layout Chunk
10515 \begin_layout Standard
10516 \begin_inset listings
10520 \begin_layout Plain Layout
10525 \begin_layout Plain Layout
10529 chunkref{constants}>
10532 \begin_layout Plain Layout
10536 chunkref{mode-definitions}>
10539 \begin_layout Plain Layout
10543 chunkref{default-options}>
10546 \begin_layout Plain Layout
10550 \begin_layout Plain Layout
10554 chunkref{read-options}>
10557 \begin_layout Plain Layout
10567 \begin_layout Standard
10568 And have a simple help function
10571 \begin_layout Chunk
10575 \begin_layout Standard
10576 \begin_inset listings
10580 \begin_layout Plain Layout
10585 \begin_layout Plain Layout
10590 \begin_layout Plain Layout
10592 print " newfangle [-L] -R<rootname> [source.tex ...]"
10595 \begin_layout Plain Layout
10597 print " newfangle -r [source.tex ...]"
10600 \begin_layout Plain Layout
10602 print " If the filename, source.tex is not specified then stdin is used"
10605 \begin_layout Plain Layout
10610 \begin_layout Plain Layout
10612 print "-L causes the C statement: #line <lineno>
10619 \begin_layout Plain Layout
10621 print "-R causes the named root to be written to stdout"
10624 \begin_layout Plain Layout
10626 print "-r lists all roots in the file (even those used elsewhere)"
10629 \begin_layout Plain Layout
10634 \begin_layout Plain Layout
10644 \begin_layout Chapter
10645 Generating the output
10648 \begin_layout Standard
10649 We generate output by calling output_chunk, or listing the chunk names.
10652 \begin_layout Chunk
10656 \begin_layout Standard
10657 \begin_inset listings
10661 \begin_layout Plain Layout
10663 if (length(root)) output_chunk(root);
10666 \begin_layout Plain Layout
10668 else output_chunk_names();
10676 \begin_layout Standard
10677 We also have some other output debugging:
10680 \begin_layout Chunk
10684 \begin_layout Standard
10685 \begin_inset listings
10689 \begin_layout Plain Layout
10694 \begin_layout Plain Layout
10696 print "------ chunk names "
10699 \begin_layout Plain Layout
10701 output_chunk_names();
10704 \begin_layout Plain Layout
10706 print "====== chunks"
10709 \begin_layout Plain Layout
10714 \begin_layout Plain Layout
10716 print "++++++ debug"
10719 \begin_layout Plain Layout
10721 for (a in chunks) {
10724 \begin_layout Plain Layout
10726 print a "=" chunks[a];
10729 \begin_layout Plain Layout
10734 \begin_layout Plain Layout
10744 \begin_layout Standard
10745 We do both of these at the end.
10747 \begin_inset Flex CharStyle:Code
10750 \begin_layout Plain Layout
10756 because each chunklet is not necessarily a complete line, and we already
10758 \begin_inset Flex CharStyle:Code
10761 \begin_layout Plain Layout
10767 to each input line in section
10768 \begin_inset CommandInset ref
10770 reference "sub:ORS-chunk-text"
10777 \begin_layout Chunk
10781 \begin_layout Standard
10782 \begin_inset listings
10786 \begin_layout Plain Layout
10791 \begin_layout Plain Layout
10795 chunkref{debug-output}>
10798 \begin_layout Plain Layout
10803 \begin_layout Plain Layout
10807 chunkref{generate-output}>
10810 \begin_layout Plain Layout
10820 \begin_layout Standard
10821 We write chunk names like this.
10822 If we seem to be running in notangle compatibility mode, then we enclose
10824 \begin_inset Flex CharStyle:Code
10827 \begin_layout Plain Layout
10833 the same way notangle does:
10836 \begin_layout Chunk
10837 output_chunk_names()
10840 \begin_layout Standard
10841 \begin_inset listings
10845 \begin_layout Plain Layout
10847 function output_chunk_names( c, prefix, suffix)
10850 \begin_layout Plain Layout
10855 \begin_layout Plain Layout
10857 if (notangle_mode) {
10860 \begin_layout Plain Layout
10865 \begin_layout Plain Layout
10870 \begin_layout Plain Layout
10875 \begin_layout Plain Layout
10877 for (c in chunk_names) {
10880 \begin_layout Plain Layout
10882 print prefix c suffix "
10887 \begin_layout Plain Layout
10892 \begin_layout Plain Layout
10902 \begin_layout Standard
10903 This function would write out all chunks
10906 \begin_layout Chunk
10910 \begin_layout Standard
10911 \begin_inset listings
10915 \begin_layout Plain Layout
10917 function output_chunks( a)
10920 \begin_layout Plain Layout
10925 \begin_layout Plain Layout
10927 for (a in chunk_names) {
10930 \begin_layout Plain Layout
10932 output_chunk(chunk_names[a]);
10935 \begin_layout Plain Layout
10940 \begin_layout Plain Layout
10945 \begin_layout Plain Layout
10949 \begin_layout Plain Layout
10951 function output_chunk(chunk) {
10954 \begin_layout Plain Layout
10959 \begin_layout Plain Layout
10961 lineno_needed = linenos;
10964 \begin_layout Plain Layout
10968 \begin_layout Plain Layout
10970 write_chunk(chunk);
10973 \begin_layout Plain Layout
10978 \begin_layout Plain Layout
10987 \begin_layout Section
10988 Assembling the chunks
10991 \begin_layout Standard
10992 \begin_inset Flex CharStyle:Code
10995 \begin_layout Plain Layout
11001 holds a string consisting of the names of all the chunks that resulted
11002 in this chunk being output.
11004 \begin_inset Note Note
11007 \begin_layout Plain Layout
11008 Make sure it includes the line numbers too...
11014 It should probably also contain the source line numbers at which each inclusion
11018 \begin_layout Chunk
11022 \begin_layout Standard
11023 We first initialize the mode tracker for this chunk.
11026 \begin_layout Standard
11027 \begin_inset listings
11031 \begin_layout Plain Layout
11033 function write_chunk(chunk_name) {
11036 \begin_layout Plain Layout
11040 chunkref{awk-delete-array}(context)>
11043 \begin_layout Plain Layout
11045 return write_chunk_r(chunk_name, context);
11048 \begin_layout Plain Layout
11058 \begin_layout Chunk
11059 write_chunk(),emph={chunk_path}
11062 \begin_layout Standard
11063 \begin_inset listings
11067 \begin_layout Plain Layout
11069 function write_chunk_r(chunk_name, context, indent, tail,
11072 \begin_layout Plain Layout
11077 \begin_layout Plain Layout
11079 chunk_path, chunk_args,
11082 \begin_layout Plain Layout
11084 s, r, src, new_src,
11087 \begin_layout Plain Layout
11092 \begin_layout Plain Layout
11094 chunk_params, part, max_part, part_line, frag, max_frag, text,
11097 \begin_layout Plain Layout
11099 chunklet, only_part, call_chunk_args, new_context)
11102 \begin_layout Plain Layout
11112 \begin_layout Subsection
11113 \begin_inset CommandInset label
11115 name "sub:Chunk-parts"
11122 \begin_layout Standard
11123 As mentioned in section
11124 \begin_inset CommandInset ref
11126 reference "sub:lstlistings-includes"
11130 , a chunk name may contain a part specifier in square brackets, limiting
11131 the parts that should be emitted.
11134 \begin_layout Standard
11135 \begin_inset listings
11139 \begin_layout Plain Layout
11141 if (match(chunk_name, "^(.*)
11149 ]$", chunk_name_parts)) {
11152 \begin_layout Plain Layout
11154 chunk_name = chunk_name_parts[1];
11157 \begin_layout Plain Layout
11159 only_part = chunk_name_parts[2];
11162 \begin_layout Plain Layout
11172 \begin_layout Standard
11173 We then create a mode tracker
11176 \begin_layout Standard
11177 \begin_inset listings
11181 \begin_layout Plain Layout
11185 chunkref{new-mode-tracker}(context, chunks[chunk_name, "language"], "")>
11193 \begin_layout Standard
11195 \begin_inset Flex CharStyle:Code
11198 \begin_layout Plain Layout
11204 the names of the parameters that this chunk accepts, whose values were
11205 (optionally) passed in
11206 \begin_inset Flex CharStyle:Code
11209 \begin_layout Plain Layout
11218 \begin_layout Standard
11219 \begin_inset listings
11223 \begin_layout Plain Layout
11225 split(chunks[chunk_name, "params"], chunk_params, " *; *");
11233 \begin_layout Standard
11234 To assemble a chunk, we write out each part.
11237 \begin_layout Chunk
11241 \begin_layout Standard
11242 \begin_inset listings
11246 \begin_layout Plain Layout
11248 if (! (chunk_name in chunk_names)) {
11251 \begin_layout Plain Layout
11253 error(sprintf(_"The root module <<%s>> was not defined.
11260 \begin_layout Plain Layout
11262 chunk_name, chunk_path));
11265 \begin_layout Plain Layout
11270 \begin_layout Plain Layout
11274 \begin_layout Plain Layout
11276 max_part = chunks[chunk_name, "part"];
11279 \begin_layout Plain Layout
11281 for(part = 1; part <= max_part; part++) {
11284 \begin_layout Plain Layout
11286 if (! only_part || part == only_part) {
11289 \begin_layout Plain Layout
11293 chunkref{write-part}>
11296 \begin_layout Plain Layout
11301 \begin_layout Plain Layout
11306 \begin_layout Plain Layout
11308 if (! finalize_mode_tracker(context)) {
11311 \begin_layout Plain Layout
11313 dump_mode_tracker(context);
11316 \begin_layout Plain Layout
11318 error(sprintf(_"Module %s did not close context properly.
11322 n", chunk_name, chunk_path));
11325 \begin_layout Plain Layout
11330 \begin_layout Plain Layout
11340 \begin_layout Standard
11341 A part can either be a chunklet of lines, or an include of another chunk.
11344 \begin_layout Standard
11345 Chunks may also have parameters, specified in LaTeX style with braces after
11346 the chunk name --- looking like this in the document:
11347 \begin_inset Flex CharStyle:Code
11350 \begin_layout Plain Layout
11351 chunkname{param1, param2}
11357 Arguments are passed in square brackets:
11358 \begin_inset Flex CharStyle:Code
11361 \begin_layout Plain Layout
11364 chunkref{chunkname}[arg1, arg2]
11372 \begin_layout Standard
11373 Before we process each part, we check that the source position hasn't changed
11374 unexpectedly, so that we can know if we need to output a new file-line
11378 \begin_layout Chunk
11382 \begin_layout Standard
11383 \begin_inset listings
11387 \begin_layout Plain Layout
11391 chunkref{check-source-jump}>
11394 \begin_layout Plain Layout
11398 \begin_layout Plain Layout
11400 chunklet = chunks[chunk_name, "part", part];
11403 \begin_layout Plain Layout
11405 if (chunks[chunk_name, "part", part, "type"] == part_type_chunk) {
11408 \begin_layout Plain Layout
11412 chunkref{write-included-chunk}>
11415 \begin_layout Plain Layout
11417 } else if (chunklet SUBSEP "line" in chunks) {
11420 \begin_layout Plain Layout
11424 chunkref{write-chunklets}>
11427 \begin_layout Plain Layout
11432 \begin_layout Plain Layout
11434 # empty last chunklet
11437 \begin_layout Plain Layout
11447 \begin_layout Standard
11448 To write an included chunk, we must detect any optional chunk arguments
11450 Then we recurse calling
11451 \begin_inset Flex Chunkref
11454 \begin_layout Plain Layout
11463 \begin_layout Chunk
11464 write-included-chunk
11467 \begin_layout Standard
11468 \begin_inset listings
11472 \begin_layout Plain Layout
11474 if (match(chunklet, "^([^
11490 )$", chunklet_parts)) {
11493 \begin_layout Plain Layout
11495 chunklet = chunklet_parts[1];
11498 \begin_layout Plain Layout
11500 parse_chunk_args("c-like", chunklet_parts[2], call_chunk_args, "(");
11503 \begin_layout Plain Layout
11505 for (c in call_chunk_args) {
11508 \begin_layout Plain Layout
11510 call_chunk_args[c] = expand_chunk_args(call_chunk_args[c], chunk_params,
11514 \begin_layout Plain Layout
11519 \begin_layout Plain Layout
11524 \begin_layout Plain Layout
11526 split("", call_chunk_args);
11529 \begin_layout Plain Layout
11534 \begin_layout Plain Layout
11536 # update the transforms arrays
11539 \begin_layout Plain Layout
11541 new_src = mode_escaper(context, s, r, src);
11544 \begin_layout Plain Layout
11548 chunkref{awk-delete-array}(new_context)>
11551 \begin_layout Plain Layout
11553 write_chunk_r(chunklet, new_context,
11556 \begin_layout Plain Layout
11558 chunks[chunk_name, "part", part, "indent"] indent,
11561 \begin_layout Plain Layout
11563 chunks[chunk_name, "part", part, "tail"],
11566 \begin_layout Plain Layout
11573 \begin_layout Plain Layout
11578 \begin_layout Plain Layout
11588 \begin_layout Standard
11589 Before we output a chunklet of lines, we first emit the file and line number
11590 if we have one, and if it is safe to do so.
11594 \begin_layout Standard
11595 Chunklets are generally broken up by includes, so the start of a chunklet
11596 is a good place to do this.
11597 Then we output each line of the chunklet.
11600 \begin_layout Standard
11601 When it is not safe, such as in the middle of a multi-line macro definition,
11603 \begin_inset Flex CharStyle:Code
11606 \begin_layout Plain Layout
11612 is set to true, and in such a case we note that we want to emit the line
11613 statement when it is next safe.
11616 \begin_layout Chunk
11620 \begin_layout Standard
11621 \begin_inset listings
11625 \begin_layout Plain Layout
11627 max_frag = chunks[chunklet, "line"];
11630 \begin_layout Plain Layout
11632 for(frag = 1; frag <= max_frag; frag++) {
11635 \begin_layout Plain Layout
11639 chunkref{write-file-line}>
11647 \begin_layout Standard
11648 We then extract the chunklet text and expand any arguments.
11651 \begin_layout Standard
11652 \begin_inset listings
11656 \begin_layout Plain Layout
11660 \begin_layout Plain Layout
11662 text = chunks[chunklet, frag];
11665 \begin_layout Plain Layout
11670 \begin_layout Plain Layout
11675 \begin_layout Plain Layout
11677 text = expand_chunk_args(text, chunk_params, chunk_args);
11685 \begin_layout Standard
11686 If the text is a single newline (which we keep separate - see
11687 \begin_inset CommandInset ref
11689 reference "lone-newline"
11693 ) then we increment the line number.
11694 In the case where this is the last line of a chunk and it is not a top-level
11695 chunk we replace the newline with an empty string --- because the chunk
11696 that included this chunk will have the newline at the end of the line that
11697 included this chunk.
11700 \begin_layout Standard
11702 \begin_inset Flex CharStyle:Code
11705 \begin_layout Plain Layout
11711 that we have started a new line, so that indentation can be managed with
11712 the following piece of text.
11715 \begin_layout Standard
11716 \begin_inset listings
11720 \begin_layout Plain Layout
11724 \begin_layout Plain Layout
11731 \begin_layout Plain Layout
11736 \begin_layout Plain Layout
11738 if (part == max_part && frag == max_frag && length(chunk_path)) {
11741 \begin_layout Plain Layout
11746 \begin_layout Plain Layout
11751 \begin_layout Plain Layout
11756 \begin_layout Plain Layout
11761 \begin_layout Plain Layout
11771 \begin_layout Standard
11772 If this text does not represent a newline, but we see that we are the first
11773 piece of text on a newline, then we prefix our text with the current indent.
11775 \begin_inset Flex CharStyle:Code
11778 \begin_layout Plain Layout
11784 is a global output-state variable, but the
11785 \begin_inset Flex CharStyle:Code
11788 \begin_layout Plain Layout
11798 \begin_layout Standard
11799 \begin_inset listings
11803 \begin_layout Plain Layout
11805 } else if (length(text) || length(tail)) {
11808 \begin_layout Plain Layout
11810 if (newline) text = indent text;
11813 \begin_layout Plain Layout
11818 \begin_layout Plain Layout
11823 \begin_layout Plain Layout
11832 \begin_layout Standard
11833 Tail will soon no longer be relevant once mode-detection is in place.
11836 \begin_layout Standard
11837 \begin_inset listings
11841 \begin_layout Plain Layout
11846 \begin_layout Plain Layout
11848 mode_tracker(context, text);
11851 \begin_layout Plain Layout
11853 print transform_escape(s, r, text, src);
11861 \begin_layout Standard
11862 If a line ends in a backslash --- suggesting continuation --- then we supress
11863 outputting file-line as it would probably break the continued lines.
11867 \begin_layout Standard
11868 \begin_inset listings
11872 \begin_layout Plain Layout
11877 \begin_layout Plain Layout
11879 lineno_suppressed = substr(lastline, length(lastline)) == "
11886 \begin_layout Plain Layout
11891 \begin_layout Plain Layout
11901 \begin_layout Standard
11902 Of course there is no point in actually outputting the source filename and
11903 line number (file-line) if they don't say anything new! We only need to
11904 emit them if they aren't what is expected, or if we we not able to emit
11905 one when they had changed.
11908 \begin_layout Chunk
11912 \begin_layout Standard
11913 \begin_inset listings
11917 \begin_layout Plain Layout
11919 if (newline && lineno_needed && ! lineno_suppressed) {
11922 \begin_layout Plain Layout
11924 filename = a_filename;
11927 \begin_layout Plain Layout
11932 \begin_layout Plain Layout
11934 print "#line " lineno "
11943 \begin_layout Plain Layout
11948 \begin_layout Plain Layout
11958 \begin_layout Standard
11959 We check if a new file-line is needed by checking if the source line matches
11960 what we (or a compiler) would expect.
11964 \begin_layout Chunk
11968 \begin_layout Standard
11969 \begin_inset listings
11973 \begin_layout Plain Layout
11975 if (linenos && (chunk_name SUBSEP "part" SUBSEP part SUBSEP "FILENAME" in
11979 \begin_layout Plain Layout
11981 a_filename = chunks[chunk_name, "part", part, "FILENAME"];
11984 \begin_layout Plain Layout
11986 a_lineno = chunks[chunk_name, "part", part, "LINENO"];
11989 \begin_layout Plain Layout
11991 if (a_filename != filename || a_lineno != lineno) {
11994 \begin_layout Plain Layout
11999 \begin_layout Plain Layout
12004 \begin_layout Plain Layout
12014 \begin_layout Chapter
12018 \begin_layout Standard
12019 Awk has pretty limited data structures, so we will use two main hashes.
12020 Uninterrupted sequences of a chunk will be stored in
12021 \begin_inset Flex CharStyle:Code
12024 \begin_layout Plain Layout
12030 and the chunklets used in a chunk will be stored in
12031 \begin_inset Flex CharStyle:Code
12034 \begin_layout Plain Layout
12043 \begin_layout Chunk
12047 \begin_layout Standard
12048 \begin_inset listings
12052 \begin_layout Plain Layout
12057 \begin_layout Plain Layout
12067 \begin_layout Standard
12069 \begin_inset Flex CharStyle:Code
12072 \begin_layout Plain Layout
12078 mentioned are not chunk parameters for parameterized chunks, as mentioned
12080 \begin_inset CommandInset ref
12082 reference "cha:Chunk Arguments"
12086 , but the lstlistings style parameters used in the
12087 \begin_inset Flex CharStyle:Code
12090 \begin_layout Plain Layout
12102 \begin_layout Plain Layout
12104 \begin_inset Flex CharStyle:Code
12107 \begin_layout Plain Layout
12113 parameter is used to hold the parameters for parameterized chunks
12121 \begin_layout Chunk
12122 chunk-storage-functions
12125 \begin_layout Standard
12126 \begin_inset listings
12130 \begin_layout Plain Layout
12132 function new_chunk(chunk_name, params,
12135 \begin_layout Plain Layout
12140 \begin_layout Plain Layout
12145 \begin_layout Plain Layout
12150 \begin_layout Plain Layout
12152 # HACK WHILE WE CHANGE TO ( ) for PARAM CHUNKS
12155 \begin_layout Plain Layout
12165 )$", "", chunk_name);
12168 \begin_layout Plain Layout
12170 if (! (chunk_name in chunk_names)) {
12173 \begin_layout Plain Layout
12175 if (debug) print "New chunk " chunk_name;
12178 \begin_layout Plain Layout
12180 chunk_names[chunk_name];
12183 \begin_layout Plain Layout
12185 for (p in params) {
12188 \begin_layout Plain Layout
12190 chunks[chunk_name, p] = params[p];
12193 \begin_layout Plain Layout
12198 \begin_layout Plain Layout
12200 if ("append" in params) {
12203 \begin_layout Plain Layout
12205 append=params["append"];
12208 \begin_layout Plain Layout
12210 if (! (append in chunk_names)) {
12213 \begin_layout Plain Layout
12215 warning("Chunk " chunk_name " is appended to chunk " append " which
12216 is not defined yet");
12219 \begin_layout Plain Layout
12224 \begin_layout Plain Layout
12229 \begin_layout Plain Layout
12231 chunk_include(append, chunk_name);
12234 \begin_layout Plain Layout
12236 chunk_line(append, ORS);
12239 \begin_layout Plain Layout
12244 \begin_layout Plain Layout
12249 \begin_layout Plain Layout
12251 active_chunk = chunk_name;
12254 \begin_layout Plain Layout
12256 prime_chunk(chunk_name);
12259 \begin_layout Plain Layout
12269 \begin_layout Standard
12270 \begin_inset listings
12274 \begin_layout Plain Layout
12278 \begin_layout Plain Layout
12280 function prime_chunk(chunk_name)
12283 \begin_layout Plain Layout
12288 \begin_layout Plain Layout
12290 chunks[chunk_name, "part", ++chunks[chunk_name, "part"] ] =
12295 \begin_layout Plain Layout
12297 chunk_name SUBSEP "chunklet" SUBSEP "" ++chunks[chunk_name, "chunklet"]
12301 \begin_layout Plain Layout
12303 chunks[chunk_name, "part", chunks[chunk_name, "part"], "FILENAME"] = FILENAME;
12306 \begin_layout Plain Layout
12308 chunks[chunk_name, "part", chunks[chunk_name, "part"], "LINENO"] = FNR
12312 \begin_layout Plain Layout
12317 \begin_layout Plain Layout
12321 \begin_layout Plain Layout
12323 function chunk_line(chunk_name, line){
12326 \begin_layout Plain Layout
12328 chunks[chunk_name, "chunklet", chunks[chunk_name, "chunklet"],
12331 \begin_layout Plain Layout
12333 ++chunks[chunk_name, "chunklet", chunks[chunk_name, "chunklet"],
12337 \begin_layout Plain Layout
12342 \begin_layout Plain Layout
12351 \begin_layout Standard
12352 Chunk include represents a
12356 statement, and stores the requirement to include another chunk.
12357 The parameter indent represents the quanity of literal text characters
12362 statement and therefore by how much additional lines of the included chunk
12363 should be indented.
12366 \begin_layout Standard
12367 \begin_inset listings
12371 \begin_layout Plain Layout
12373 function chunk_include(chunk_name, chunk_ref, indent, tail)
12376 \begin_layout Plain Layout
12381 \begin_layout Plain Layout
12383 chunks[chunk_name, "part", ++chunks[chunk_name, "part"] ] = chunk_ref;
12386 \begin_layout Plain Layout
12388 chunks[chunk_name, "part", chunks[chunk_name, "part"], "type" ] = part_type_ch
12392 \begin_layout Plain Layout
12394 chunks[chunk_name, "part", chunks[chunk_name, "part"], "indent" ] = indent_str
12398 \begin_layout Plain Layout
12400 chunks[chunk_name, "part", chunks[chunk_name, "part"], "tail" ] = tail;
12403 \begin_layout Plain Layout
12405 prime_chunk(chunk_name);
12408 \begin_layout Plain Layout
12413 \begin_layout Plain Layout
12422 \begin_layout Standard
12423 The indent is calculated by indent_string, which may in future convert some
12424 spaces into tab characters.
12425 This function works by generating a printf padded format string, like
12426 \begin_inset Flex CharStyle:Code
12429 \begin_layout Plain Layout
12435 for an indent of 22, and then printing an empty string using that format.
12438 \begin_layout Standard
12439 \begin_inset listings
12443 \begin_layout Plain Layout
12445 function indent_string(indent) {
12448 \begin_layout Plain Layout
12450 return sprintf("%" indent "s", "");
12453 \begin_layout Plain Layout
12463 \begin_layout Chapter
12464 \begin_inset CommandInset label
12473 \begin_layout Standard
12474 I use Arnold Robbins public domain getopt (1993 revision).
12475 This is probably the same one that is covered in chapter 12 of
12476 \begin_inset Quotes eld
12479 Edition 3 of GAWK: Effective AWK Programming: A User's Guide for GNU Awk
12480 \begin_inset Quotes erd
12483 but as that is licensed under the GNU Free Documentation License, Version
12484 1.3, which conflicts with the GPL3, I can't use it from there (or it's accompany
12485 ing explanations), so I do my best to explain how it works here.
12488 \begin_layout Standard
12489 The getopt.awk header is:
12492 \begin_layout Chunk
12493 getopt.awk-header,language=awk,morestring=[b]{/},morekeywords=else
12496 \begin_layout Standard
12497 \begin_inset listings
12501 \begin_layout Plain Layout
12503 # getopt.awk --- do C library getopt(3) function in awk
12506 \begin_layout Plain Layout
12511 \begin_layout Plain Layout
12513 # Arnold Robbins, arnold@skeeve.com, Public Domain
12516 \begin_layout Plain Layout
12521 \begin_layout Plain Layout
12523 # Initial version: March, 1991
12526 \begin_layout Plain Layout
12528 # Revised: May, 1993
12531 \begin_layout Plain Layout
12540 \begin_layout Standard
12541 The provided explanation is:
12544 \begin_layout Chunk
12548 \begin_layout Standard
12549 \begin_inset listings
12553 \begin_layout Plain Layout
12555 # External variables:
12558 \begin_layout Plain Layout
12560 # Optind -- index in ARGV of first nonoption argument
12563 \begin_layout Plain Layout
12565 # Optarg -- string value of argument to current option
12568 \begin_layout Plain Layout
12570 # Opterr -- if nonzero, print our own diagnostic
12573 \begin_layout Plain Layout
12575 # Optopt -- current option letter
12578 \begin_layout Plain Layout
12582 \begin_layout Plain Layout
12587 \begin_layout Plain Layout
12589 # -1 at end of options
12592 \begin_layout Plain Layout
12594 # ? for unrecognized option
12597 \begin_layout Plain Layout
12599 # <c> a character representing the current option
12602 \begin_layout Plain Layout
12606 \begin_layout Plain Layout
12611 \begin_layout Plain Layout
12613 # _opti -- index in multi-flag option, e.g., -abc
12616 \begin_layout Plain Layout
12625 \begin_layout Standard
12626 The function follows.
12627 The final two parameters,
12628 \begin_inset Flex CharStyle:Code
12631 \begin_layout Plain Layout
12638 \begin_inset Flex CharStyle:Code
12641 \begin_layout Plain Layout
12647 are local variables and not parameters --- as indicated by the multiple
12648 spaces preceding them.
12649 Awk doesn't care, the multiple spaces are a convention to help us humans.
12652 \begin_layout Chunk
12653 getopt.awk-getopt()
12656 \begin_layout Standard
12657 \begin_inset listings
12661 \begin_layout Plain Layout
12663 function getopt(argc, argv, options, thisopt, i)
12666 \begin_layout Plain Layout
12671 \begin_layout Plain Layout
12673 if (length(options) == 0) # no options given
12676 \begin_layout Plain Layout
12681 \begin_layout Plain Layout
12683 if (argv[Optind] == "--") { # all done
12686 \begin_layout Plain Layout
12691 \begin_layout Plain Layout
12696 \begin_layout Plain Layout
12701 \begin_layout Plain Layout
12703 } else if (argv[Optind] !~ /^-[^:
12718 \begin_layout Plain Layout
12723 \begin_layout Plain Layout
12728 \begin_layout Plain Layout
12733 \begin_layout Plain Layout
12738 \begin_layout Plain Layout
12743 \begin_layout Plain Layout
12745 thisopt = substr(argv[Optind], _opti, 1)
12748 \begin_layout Plain Layout
12753 \begin_layout Plain Layout
12755 i = index(options, thisopt)
12758 \begin_layout Plain Layout
12763 \begin_layout Plain Layout
12768 \begin_layout Plain Layout
12770 printf("%c -- invalid option
12775 \begin_layout Plain Layout
12777 thisopt) > "/dev/stderr"
12780 \begin_layout Plain Layout
12782 if (_opti >= length(argv[Optind])) {
12785 \begin_layout Plain Layout
12790 \begin_layout Plain Layout
12795 \begin_layout Plain Layout
12800 \begin_layout Plain Layout
12805 \begin_layout Plain Layout
12810 \begin_layout Plain Layout
12820 \begin_layout Standard
12821 At this point, the option has been found and we need to know if it takes
12825 \begin_layout Standard
12826 \begin_inset listings
12830 \begin_layout Plain Layout
12832 if (substr(options, i + 1, 1) == ":") {
12835 \begin_layout Plain Layout
12837 # get option argument
12840 \begin_layout Plain Layout
12842 if (length(substr(argv[Optind], _opti + 1)) > 0)
12845 \begin_layout Plain Layout
12847 Optarg = substr(argv[Optind], _opti + 1)
12850 \begin_layout Plain Layout
12855 \begin_layout Plain Layout
12857 Optarg = argv[++Optind]
12860 \begin_layout Plain Layout
12865 \begin_layout Plain Layout
12870 \begin_layout Plain Layout
12875 \begin_layout Plain Layout
12877 if (_opti == 0 || _opti >= length(argv[Optind])) {
12880 \begin_layout Plain Layout
12885 \begin_layout Plain Layout
12890 \begin_layout Plain Layout
12895 \begin_layout Plain Layout
12900 \begin_layout Plain Layout
12905 \begin_layout Plain Layout
12912 A test program is built in, too
12915 \begin_layout Chunk
12919 \begin_layout Standard
12920 \begin_inset listings
12924 \begin_layout Plain Layout
12929 \begin_layout Plain Layout
12931 Opterr = 1 # default is to diagnose
12934 \begin_layout Plain Layout
12936 Optind = 1 # skip ARGV[0]
12939 \begin_layout Plain Layout
12944 \begin_layout Plain Layout
12946 if (_getopt_test) {
12949 \begin_layout Plain Layout
12951 while ((_go_c = getopt(ARGC, ARGV, "ab:cd")) != -1)
12954 \begin_layout Plain Layout
12956 printf("c = <%c>, optarg = <%s>
12961 \begin_layout Plain Layout
12966 \begin_layout Plain Layout
12968 printf("non-option arguments:
12973 \begin_layout Plain Layout
12975 for (; Optind < ARGC; Optind++)
12978 \begin_layout Plain Layout
12987 \begin_layout Plain Layout
12989 Optind, ARGV[Optind])
12992 \begin_layout Plain Layout
12997 \begin_layout Plain Layout
13007 \begin_layout Standard
13008 The entire getopt.awk is made out of these chunks in order
13011 \begin_layout Chunk
13015 \begin_layout Standard
13016 \begin_inset listings
13020 \begin_layout Plain Layout
13024 chunkref{getopt.awk-header}>
13027 \begin_layout Plain Layout
13031 \begin_layout Plain Layout
13035 chunkref{getopt.awk-notes}>
13038 \begin_layout Plain Layout
13042 chunkref{getopt.awk-getopt()}>
13045 \begin_layout Plain Layout
13049 chunkref{getopt.awk-begin}>
13057 \begin_layout Standard
13058 Although we only want the header and function:
13061 \begin_layout Chunk
13065 \begin_layout Standard
13066 \begin_inset listings
13070 \begin_layout Plain Layout
13072 # try: locate getopt.awk for the full original file
13075 \begin_layout Plain Layout
13077 # as part of your standard awk installation
13080 \begin_layout Plain Layout
13084 chunkref{getopt.awk-header}>
13087 \begin_layout Plain Layout
13091 \begin_layout Plain Layout
13095 chunkref{getopt.awk-getopt()}>
13103 \begin_layout Chapter
13104 Newfangle LaTeX source code
13107 \begin_layout Section
13111 \begin_layout Standard
13112 Here we define a Lyx .module file that makes it convenient to use LyX for
13113 writing such literate programs.
13116 \begin_layout Standard
13118 \begin_inset Flex CharStyle:Code
13121 \begin_layout Plain Layout
13127 can be installed in your personal
13128 \begin_inset Flex CharStyle:Code
13131 \begin_layout Plain Layout
13132 .lyx/layouts folder
13138 You will need to Tools Reconfigure so that LyX notices it.
13139 It adds a new format Chunk, which should precede every listing and contain
13144 \begin_layout Chunk
13145 ./newfangle.module,language=
13148 \begin_layout Standard
13149 \begin_inset listings
13153 \begin_layout Plain Layout
13157 DeclareLyXModule{Newfangle Literate Listings}
13160 \begin_layout Plain Layout
13165 \begin_layout Plain Layout
13167 # Newfangle literate listings allow one to write
13170 \begin_layout Plain Layout
13172 # literate programs after the fashion of noweb, but without having
13175 \begin_layout Plain Layout
13177 # to use noweave to generate the documentation.
13178 Instead the listings
13181 \begin_layout Plain Layout
13183 # package is extended in conjunction with the noweb package to implement
13186 \begin_layout Plain Layout
13188 # to code formating directly as latex.
13191 \begin_layout Plain Layout
13193 # The newfangle awk script
13196 \begin_layout Plain Layout
13201 \begin_layout Plain Layout
13205 \begin_layout Plain Layout
13209 chunkref{gpl3-copyright.hashed}>
13212 \begin_layout Plain Layout
13216 \begin_layout Plain Layout
13221 \begin_layout Plain Layout
13225 \begin_layout Plain Layout
13230 \begin_layout Plain Layout
13234 chunkref{./newfangle.sty}>
13237 \begin_layout Plain Layout
13242 \begin_layout Plain Layout
13246 \begin_layout Plain Layout
13250 chunkref{chunkstyle}>
13253 \begin_layout Plain Layout
13257 \begin_layout Plain Layout
13261 chunkref{chunkref}>
13269 \begin_layout Standard
13270 Because LyX modules are not yet a language supported by newfangle or lstlistings
13271 , we resort to this fake awk chunk below in order to have each line of the
13272 GPL3 license commence with a #
13275 \begin_layout Chunk
13276 gpl3-copyright.hashed,language=awk
13279 \begin_layout Standard
13280 \begin_inset listings
13284 \begin_layout Plain Layout
13288 chunkref{gpl3-copyright}>
13291 \begin_layout Plain Layout
13300 \begin_layout Subsection
13304 \begin_layout Standard
13309 style is to make it easier for LyX users to provide the name to
13310 \begin_inset Flex CharStyle:Code
13313 \begin_layout Plain Layout
13322 Normally this requires right-clicking on the listing, choosing settings,
13323 advanced, and then typing
13324 \begin_inset Flex CharStyle:Code
13327 \begin_layout Plain Layout
13334 This has the further disadvantage that the name (and other options) are
13335 not generally visible during document editing.
13338 \begin_layout Standard
13339 The chunk style is defined as a LaTeX command, so that all text on the same
13340 line is passed to the LaTeX command
13341 \begin_inset Flex CharStyle:Code
13344 \begin_layout Plain Layout
13351 This makes it easy to parse using
13352 \begin_inset Flex CharStyle:Code
13355 \begin_layout Plain Layout
13361 , and easy to pass these options on to the listings package.
13362 The first word in a chunk section should be the chunk name, and will have
13364 \begin_inset Flex CharStyle:Code
13367 \begin_layout Plain Layout
13374 Any other words are accepted arguments to
13375 \begin_inset Flex CharStyle:Code
13378 \begin_layout Plain Layout
13389 \begin_layout Standard
13390 We set PassThru to 1 because the user is actually entering raw latex.
13393 \begin_layout Chunk
13397 \begin_layout Standard
13398 \begin_inset listings
13402 \begin_layout Plain Layout
13407 \begin_layout Plain Layout
13412 \begin_layout Plain Layout
13417 \begin_layout Plain Layout
13419 Margin First_Dynamic
13422 \begin_layout Plain Layout
13424 LeftMargin Chunk:xxx
13427 \begin_layout Plain Layout
13432 \begin_layout Plain Layout
13437 \begin_layout Plain Layout
13439 LabelString "Chunk:"
13442 \begin_layout Plain Layout
13447 \begin_layout Plain Layout
13452 \begin_layout Plain Layout
13461 \begin_layout Standard
13462 To make the label very visible we choose a larger font coloured red.
13465 \begin_layout Standard
13466 \begin_inset listings
13470 \begin_layout Plain Layout
13475 \begin_layout Plain Layout
13480 \begin_layout Plain Layout
13485 \begin_layout Plain Layout
13490 \begin_layout Plain Layout
13495 \begin_layout Plain Layout
13500 \begin_layout Plain Layout
13505 \begin_layout Plain Layout
13515 \begin_layout Subsection
13519 \begin_layout Standard
13520 We also define the Chunkref style which can be used to express cross references
13524 \begin_layout Chunk
13528 \begin_layout Standard
13529 \begin_inset listings
13533 \begin_layout Plain Layout
13535 InsetLayout Chunkref
13538 \begin_layout Plain Layout
13543 \begin_layout Plain Layout
13548 \begin_layout Plain Layout
13553 \begin_layout Plain Layout
13558 \begin_layout Plain Layout
13563 \begin_layout Plain Layout
13568 \begin_layout Plain Layout
13573 \begin_layout Plain Layout
13578 \begin_layout Plain Layout
13588 \begin_layout Section
13589 \begin_inset CommandInset label
13591 name "sec:Latex-Macros"
13598 \begin_layout Standard
13612 As noweb defines it's own
13613 \begin_inset Flex CharStyle:Code
13616 \begin_layout Plain Layout
13624 environment, we re-define the one that LyX logical markup module expects
13628 \begin_layout Chunk
13629 ./newfangle.sty,language=tex,basicstyle=
13634 \begin_layout Standard
13635 \begin_inset listings
13639 \begin_layout Plain Layout
13643 usepackage{listings}%
13646 \begin_layout Plain Layout
13653 \begin_layout Plain Layout
13660 \begin_layout Plain Layout
13676 \begin_layout Standard
13678 \begin_inset Flex CharStyle:Code
13681 \begin_layout Plain Layout
13688 \begin_inset Flex CharStyle:Code
13691 \begin_layout Plain Layout
13699 which will need renaming to
13700 \begin_inset Flex CharStyle:Code
13703 \begin_layout Plain Layout
13711 when I can do this without clashing with
13712 \begin_inset Flex CharStyle:Code
13715 \begin_layout Plain Layout
13726 \begin_layout Standard
13727 \begin_inset listings
13731 \begin_layout Plain Layout
13735 lstnewenvironment{Chunk}{
13747 \begin_layout Standard
13748 We also define a suitable
13749 \begin_inset Flex CharStyle:Code
13752 \begin_layout Plain Layout
13760 of parameters that suit the literate programming style after the fashion
13768 \begin_layout Standard
13769 \begin_inset listings
13773 \begin_layout Plain Layout
13777 lstset{numbers=left, stepnumber=5, numbersep=5pt,
13780 \begin_layout Plain Layout
13782 breaklines=false,basicstyle=
13787 \begin_layout Plain Layout
13799 \begin_layout Standard
13800 We also define a notangle-like mechanism for
13804 to LaTeX from the listing, and by which we can refer to other listings.
13806 \begin_inset Flex CharStyle:Code
13809 \begin_layout Plain Layout
13810 =<\SpecialChar \ldots{}
13816 sequence to contain LaTeX code, and include another like this chunk:
13817 \begin_inset Flex CharStyle:Code
13820 \begin_layout Plain Layout
13823 chunkref{chunkname}>
13830 \begin_inset Flex CharStyle:Code
13833 \begin_layout Plain Layout
13834 =<\SpecialChar \ldots{}
13840 is already defined to contain LaTeX code for this document --- this is
13845 document after all --- the code fragment below effectively contains the
13847 \begin_inset Flex CharStyle:Code
13850 \begin_layout Plain Layout
13857 To avoid problems with document generation, I had to declare an lstlistings
13859 \begin_inset Flex CharStyle:Code
13862 \begin_layout Plain Layout
13868 for this listing only; which in LyX was done by right-clicking the listings
13870 \begin_inset Flex CharStyle:Code
13873 \begin_layout Plain Layout
13879 \SpecialChar \menuseparator
13881 \begin_inset Flex CharStyle:Code
13884 \begin_layout Plain Layout
13893 \begin_layout Standard
13894 \begin_inset Note Note
13897 \begin_layout Plain Layout
13898 =< isn't enjoyed literally here, in a listing when the escape sequence is
13899 already defined as shown...
13900 we need to somehow escape this representation...
13908 \begin_layout Standard
13909 \begin_inset listings
13910 lstparams "escapeinside={}"
13914 \begin_layout Plain Layout
13918 lstset{escapeinside={=<}{>}}%
13926 \begin_layout Standard
13927 Although our macros will contain the @ symbol, they will be included in
13929 \begin_inset Flex CharStyle:Code
13932 \begin_layout Plain Layout
13940 section by LyX; however we keep the commented out
13941 \begin_inset Flex CharStyle:Code
13944 \begin_layout Plain Layout
13953 The listings package likes to centre the titles, but noweb titles are specially
13954 formatted and must be left aligned.
13955 The simplest way to do this turned out to be by removing the definition
13957 \begin_inset Flex CharStyle:Code
13960 \begin_layout Plain Layout
13969 This may interact badly if other listings want a regular title or caption.
13970 We remember the old maketitle in case we need it.
13973 \begin_layout Standard
13974 \begin_inset listings
13978 \begin_layout Plain Layout
13985 \begin_layout Plain Layout
13987 %somehow re-defining maketitle gives us a left-aligned title
13990 \begin_layout Plain Layout
13992 %which is extactly what our specially formatted title needs!
13995 \begin_layout Plain Layout
14003 newfangle@lst@maketitle
14008 \begin_layout Plain Layout
14024 \begin_layout Subsection
14025 \begin_inset CommandInset label
14027 name "sub:The-chunk-command"
14034 \begin_layout Standard
14035 Our chunk command accepts one argument, and calls
14036 \begin_inset Flex CharStyle:Code
14039 \begin_layout Plain Layout
14049 \begin_inset Flex CharStyle:Code
14052 \begin_layout Plain Layout
14060 will note the name, this is erased when the next
14061 \begin_inset Flex CharStyle:Code
14064 \begin_layout Plain Layout
14072 starts, so we make a note of this in
14073 \begin_inset Flex CharStyle:Code
14076 \begin_layout Plain Layout
14084 and restore in in lstlistings Init hook.
14087 \begin_layout Standard
14088 \begin_inset listings
14092 \begin_layout Plain Layout
14101 \begin_layout Plain Layout
14107 newfanglecaption},name=#1}%
14110 \begin_layout Plain Layout
14123 \begin_layout Plain Layout
14128 \begin_layout Plain Layout
14144 \begin_layout Subsubsection
14148 \begin_layout Standard
14149 Newfangle permits parameterized chunks, and requires the paramters to be
14150 specified as listings options.
14151 The newfangle script uses this, and although we don't do anything with
14152 these in the LaTeX code right now, we need to stop the listings package
14156 \begin_layout Standard
14157 \begin_inset listings
14161 \begin_layout Plain Layout
14171 newfangle@chunk@params{#1}}%
14179 \begin_layout Standard
14180 As it is common to define a chunk which then needs appending to another
14181 chunk, and annoying to have to declare a single line chunk to manage the
14182 include, we support an
14183 \begin_inset Flex CharStyle:Code
14186 \begin_layout Plain Layout
14196 \begin_layout Standard
14197 \begin_inset listings
14201 \begin_layout Plain Layout
14211 newfangle@chunk@append{#1}}%
14219 \begin_layout Subsection
14220 The noweb styled caption
14223 \begin_layout Standard
14224 We define a public macro
14225 \begin_inset Flex CharStyle:Code
14228 \begin_layout Plain Layout
14236 which can be set as a regular title.
14238 \begin_inset Flex CharStyle:Code
14241 \begin_layout Plain Layout
14250 \begin_inset Flex CharStyle:Code
14253 \begin_layout Plain Layout
14261 at the appriate time when the caption is emitted.
14264 \begin_layout Standard
14265 \begin_inset listings
14269 \begin_layout Plain Layout
14279 newfangle@caption}%
14287 \begin_layout Standard
14288 \begin_inset Float figure
14294 \begin_layout Plain Layout
14295 \begin_inset Box Boxed
14304 height_special "totalheight"
14307 \begin_layout Plain Layout
14309 \begin_inset space \qquad{}
14317 \begin_inset Formula $\equiv+$
14321 \begin_inset space \qquad{}
14325 \begin_inset space \qquad{}
14329 \begin_inset space \qquad{}
14333 \begin_inset Formula $\triangleleft$
14337 \begin_inset space \quad{}
14341 \begin_inset Formula $\triangleright$
14347 \begin_layout Plain Layout
14350 In this example, the current chunk is 22c, and therefore the third chunk
14354 \begin_layout Plain Layout
14365 \begin_layout Plain Layout
14368 The first chunk with this name (19b) occurs as the second chunk on page
14372 \begin_layout Plain Layout
14375 The previous chunk (22d) with the same name is the second chunk on page
14379 \begin_layout Plain Layout
14382 The next chunk (24d) is the fourth chunk on page 24.
14385 \begin_layout Plain Layout
14386 \begin_inset Caption
14388 \begin_layout Plain Layout
14404 The general noweb output format compactly identifies the current chunk,
14405 and references to the first chunk, and the previous and next chunks that
14406 have the same name.
14410 \begin_layout Standard
14411 This means that we need to keep a counter for each chunk-name, that we use
14412 to count chunks of the same name.
14416 \begin_layout Subsection
14420 \begin_layout Standard
14421 It would be natural to have a counter for each chunk name, but TeX would
14422 soon run out of counters
14426 \begin_layout Plain Layout
14427 \SpecialChar \ldots{}
14432 run out of counters and so I had to re-write the LaTeX macros to share
14433 a counter as described here
14438 , so we have one counter which we save at the end of a chunk and restore
14439 at the beginning of a chunk.
14442 \begin_layout Standard
14443 \begin_inset listings
14447 \begin_layout Plain Layout
14451 newcounter{newfangle@chunkcounter}%
14459 \begin_layout Standard
14460 We construct the name of this variable to store the counter to be the text
14462 \begin_inset Flex CharStyle:Code
14465 \begin_layout Plain Layout
14471 prefixed onto the chunks own name, and store it in
14472 \begin_inset Flex CharStyle:Code
14475 \begin_layout Plain Layout
14487 \begin_layout Standard
14488 We save the counter like this:
14491 \begin_layout Chunk
14495 \begin_layout Standard
14496 \begin_inset listings
14500 \begin_layout Plain Layout
14516 arabic{newfangle@chunkcounter}}%
14524 \begin_layout Standard
14525 and restore the counter like this:
14528 \begin_layout Chunk
14532 \begin_layout Standard
14533 \begin_inset listings
14537 \begin_layout Plain Layout
14541 setcounter{newfangle@chunkcounter}{
14555 \begin_layout Chunk
14559 \begin_layout Standard
14560 If there does not already exist a variable whose name is stored in
14561 \begin_inset Flex CharStyle:Code
14564 \begin_layout Plain Layout
14572 , then we know we are the first chunk with this name, and then define a
14577 \begin_layout Standard
14578 Although chunks of the same name share a common counter, they must still
14580 We use is the internal name of the listing, suffixed by the counter value.
14581 So the first chunk might be
14582 \begin_inset Flex CharStyle:Code
14585 \begin_layout Plain Layout
14591 and the second chunk be
14592 \begin_inset Flex CharStyle:Code
14595 \begin_layout Plain Layout
14604 \begin_layout Standard
14605 We also calculate the name of the previous chunk if we can (before we increment
14606 the chunk counter).
14607 If this is the first chunk of that name, then
14608 \begin_inset Flex CharStyle:Code
14611 \begin_layout Plain Layout
14620 \begin_inset Flex CharStyle:Code
14623 \begin_layout Plain Layout
14631 which the noweb package will interpret as not existing.
14634 \begin_layout Standard
14635 \begin_inset listings
14639 \begin_layout Plain Layout
14645 newfangle@caption{%
14648 \begin_layout Plain Layout
14654 chunkcount{lst-chunk-
14659 \begin_layout Plain Layout
14668 \begin_layout Plain Layout
14683 \begin_layout Plain Layout
14687 setcounter{newfangle@chunkcounter}{
14696 \begin_layout Plain Layout
14707 \begin_layout Plain Layout
14712 \begin_layout Plain Layout
14716 setcounter{newfangle@chunkcounter}{
14725 \begin_layout Plain Layout
14735 arabic{newfangle@chunkcounter}}%
14738 \begin_layout Plain Layout
14748 \begin_layout Standard
14749 After incrementing the chunk counter, we then define the name of this chunk,
14750 as well as the name of the first chunk.
14753 \begin_layout Standard
14754 \begin_inset listings
14758 \begin_layout Plain Layout
14762 addtocounter{newfangle@chunkcounter}{1}%
14765 \begin_layout Plain Layout
14781 arabic{newfangle@chunkcounter}}%
14784 \begin_layout Plain Layout
14794 arabic{newfangle@chunkcounter}}%
14797 \begin_layout Plain Layout
14813 \begin_layout Standard
14814 We now need to calculate the name of the next chunk.
14815 We do this by temporarily skipping the counter on by one; however there
14816 may not actually be another chunk with this name! We detect this by also
14817 defining a label for each chunk based on the chunkname.
14818 If there is a next chunkname then it will define a label with that name.
14819 As labels are persistent, we can at least tell the second time LaTeX is
14821 If we don't find such a defined label then we define
14822 \begin_inset Flex CharStyle:Code
14825 \begin_layout Plain Layout
14834 \begin_inset Flex CharStyle:Code
14837 \begin_layout Plain Layout
14848 \begin_layout Standard
14849 \begin_inset listings
14853 \begin_layout Plain Layout
14857 addtocounter{newfangle@chunkcounter}{1}%
14860 \begin_layout Plain Layout
14870 arabic{newfangle@chunkcounter}}%
14873 \begin_layout Plain Layout
14877 @ifundefined{r@label-
14893 \begin_layout Standard
14894 The noweb package requires that we define a
14895 \begin_inset Flex CharStyle:Code
14898 \begin_layout Plain Layout
14906 for every chunk, with a unique name, which is then used to print out it's
14910 \begin_layout Standard
14911 We also define a regular label for this chunk, as was mentioned above when
14913 \begin_inset Flex CharStyle:Code
14916 \begin_layout Plain Layout
14925 This requires LaTeX to be run at least twice after new chunk sections are
14926 added --- but noweb requried that anyway.
14929 \begin_layout Standard
14930 \begin_inset listings
14934 \begin_layout Plain Layout
14943 \begin_layout Plain Layout
14945 % define this label for every chunk instance, so we
14948 \begin_layout Plain Layout
14950 % can tell when we are the last chunk of this name
14953 \begin_layout Plain Layout
14967 \begin_layout Standard
14968 We also try and add the chunk to the list of listings, but I'm afraid we
14969 don't do very well.
14970 We want each chunk name listing once, with all of it's references.
14973 \begin_layout Standard
14974 \begin_inset listings
14978 \begin_layout Plain Layout
14982 addcontentsline{lol}{lstlisting}{
14998 \begin_layout Standard
14999 We then call the noweb output macros in the same way that noweave generates
15000 them, except that we don't need to call
15001 \begin_inset Flex CharStyle:Code
15004 \begin_layout Plain Layout
15007 nwstartdeflinemarkup
15013 \begin_inset Flex CharStyle:Code
15016 \begin_layout Plain Layout
15024 -- and if we do it messes up the output somewhat.
15027 \begin_layout Standard
15028 \begin_inset listings
15032 \begin_layout Plain Layout
15039 \begin_layout Plain Layout
15044 \begin_layout Plain Layout
15051 \begin_layout Plain Layout
15060 \begin_layout Plain Layout
15065 \begin_layout Plain Layout
15070 \begin_layout Plain Layout
15075 \begin_layout Plain Layout
15082 \begin_layout Plain Layout
15089 \begin_layout Plain Layout
15094 \begin_layout Plain Layout
15103 \begin_layout Plain Layout
15107 @ifundefined{newfangle@chunk@params}{}{%
15110 \begin_layout Plain Layout
15114 newfangle@chunk@params)%
15117 \begin_layout Plain Layout
15122 \begin_layout Plain Layout
15133 \begin_layout Plain Layout
15142 \begin_layout Plain Layout
15147 \begin_layout Plain Layout
15151 @ifundefined{newfangle@chunk@append}{}{%
15154 \begin_layout Plain Layout
15160 newfangle@chunk@append{x}
15165 \begin_layout Plain Layout
15169 newfangle@chunk@append%
15172 \begin_layout Plain Layout
15179 \begin_layout Plain Layout
15184 \begin_layout Plain Layout
15192 newfangle@chunk@append{}%
15195 \begin_layout Plain Layout
15202 \begin_layout Plain Layout
15207 \begin_layout Plain Layout
15212 \begin_layout Plain Layout
15231 \begin_layout Plain Layout
15235 nwstartdeflinemarkup%
15238 \begin_layout Plain Layout
15249 \begin_layout Plain Layout
15253 nwenddeflinemarkup%
15256 \begin_layout Plain Layout
15266 \begin_layout Standard
15267 Originally this was developed as a
15268 \begin_inset Flex CharStyle:Code
15271 \begin_layout Plain Layout
15277 aspect, in the Init hook, but it was found easier to affect the title without
15279 \begin_inset Flex CharStyle:Code
15282 \begin_layout Plain Layout
15285 lst@AddToHookExe{PreSet}
15290 is still required to set the listings name to the name passed to the
15291 \begin_inset Flex CharStyle:Code
15294 \begin_layout Plain Layout
15305 \begin_layout Standard
15306 \begin_inset listings
15310 \begin_layout Plain Layout
15314 lst@BeginAspect{newfangle}
15317 \begin_layout Plain Layout
15321 lst@Key{newfangle}{true}[t]{
15323 lstKV@SetIf{#1}{true}}
15326 \begin_layout Plain Layout
15330 lst@AddToHookExe{PreSet}{
15341 \begin_layout Plain Layout
15345 lst@AddToHook{Init}{}%
15350 \begin_layout Plain Layout
15362 \begin_layout Subsection
15366 \begin_layout Standard
15369 chunkref command which makes it easy to generate visual references to different
15373 \begin_layout Standard
15374 \begin_inset Tabular
15375 <lyxtabular version="3" rows="4" columns="2">
15377 <column alignment="center" valignment="top" width="0">
15378 <column alignment="center" valignment="top" width="0">
15380 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
15383 \begin_layout Plain Layout
15389 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
15392 \begin_layout Plain Layout
15400 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
15403 \begin_layout Plain Layout
15411 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
15414 \begin_layout Plain Layout
15418 \begin_layout Plain Layout
15434 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
15437 \begin_layout Plain Layout
15440 chunkref[3]{preamble}
15445 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
15448 \begin_layout Plain Layout
15452 \begin_layout Plain Layout
15456 chunkref[3]{preamble}
15468 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
15471 \begin_layout Plain Layout
15474 chunkref{preamble}[arg1, arg2]
15479 <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
15482 \begin_layout Plain Layout
15486 \begin_layout Plain Layout
15490 chunkref{preamble}[arg1, arg2]
15508 \begin_layout Standard
15509 Chunkref can also be used within a code chunk to include another code chunk.
15510 The third optional parameter to chunkref is a comma sepatarated list of
15511 arguments, which will replace defined parameters in the chunkref.
15512 \begin_inset Note Note
15515 \begin_layout Plain Layout
15516 Darn it, if I have: =<
15518 chunkref{new-mode-tracker}[{chunks[chunk_name, "language"]},{mode}]> the
15519 inner braces (inside [ ]) cause _ to signify subscript even though we have
15528 \begin_layout Standard
15529 \begin_inset listings
15533 \begin_layout Plain Layout
15542 \begin_layout Plain Layout
15551 \begin_layout Plain Layout
15562 \begin_layout Plain Layout
15569 \begin_layout Plain Layout
15580 \begin_layout Plain Layout
15585 \begin_layout Plain Layout
15594 \begin_layout Plain Layout
15600 chunkref@i{#1}{#2}}{
15602 chunkref@i{#1}{#2}()}%
15605 \begin_layout Plain Layout
15610 \begin_layout Plain Layout
15616 chunkref@i#1#2(#3){%
15619 \begin_layout Plain Layout
15628 \begin_layout Plain Layout
15637 \begin_layout Plain Layout
15646 \begin_layout Plain Layout
15655 \begin_layout Plain Layout
15666 \begin_layout Plain Layout
15675 \begin_layout Plain Layout
15682 \begin_layout Plain Layout
15693 \begin_layout Plain Layout
15700 \begin_layout Plain Layout
15711 \begin_layout Plain Layout
15722 \begin_layout Plain Layout
15731 \begin_layout Plain Layout
15738 \begin_layout Plain Layout
15743 \begin_layout Plain Layout
15752 \begin_layout Plain Layout
15763 \begin_layout Plain Layout
15770 \begin_layout Plain Layout
15777 \begin_layout Plain Layout
15784 \begin_layout Plain Layout
15795 \begin_layout Plain Layout
15802 \begin_layout Plain Layout
15806 chunkref@args #3,)%
15809 \begin_layout Plain Layout
15816 \begin_layout Plain Layout
15825 \begin_layout Plain Layout
15830 \begin_layout Plain Layout
15835 \begin_layout Plain Layout
15844 \begin_layout Plain Layout
15854 \begin_layout Subsection
15858 \begin_layout Standard
15859 \begin_inset listings
15863 \begin_layout Plain Layout
15868 \begin_layout Plain Layout
15880 \begin_layout Chapter
15881 Extracting newfangle
15884 \begin_layout Section
15885 Extracting from Lyx
15888 \begin_layout Standard
15889 To extract from LyX, you will need to configure LyX as explained in section
15891 \begin_inset CommandInset ref
15893 reference "sub:Configuring-the-build"
15900 \begin_layout Standard
15901 \begin_inset CommandInset label
15903 name "lyx-build-script"
15907 And this lyx-build scrap will extract newfangle for me.
15910 \begin_layout Chunk
15911 lyx-build,language=sh
15914 \begin_layout Standard
15915 \begin_inset listings
15919 \begin_layout Plain Layout
15924 \begin_layout Plain Layout
15929 \begin_layout Plain Layout
15933 \begin_layout Plain Layout
15937 chunkref{lyx-build-helper}>
15940 \begin_layout Plain Layout
15942 cd $PROJECT_DIR || exit 1
15945 \begin_layout Plain Layout
15949 \begin_layout Plain Layout
15951 /usr/local/bin/newfangle -R./newfangle $TEX_SRC > ./newfangle
15954 \begin_layout Plain Layout
15956 /usr/local/bin/newfangle -R./newfangle.module $TEX_SRC > ./newfangle.module
15959 \begin_layout Plain Layout
15963 \begin_layout Plain Layout
15967 chunkref{test:helpers}>
15970 \begin_layout Plain Layout
15972 export NEWFANGLE=./newfangle
15975 \begin_layout Plain Layout
15977 export TMP=${TMP:-/tmp}
15980 \begin_layout Plain Layout
15984 chunkref{test:run-tests}>
15987 \begin_layout Plain Layout
15989 # Now check that we can extract a newfangle that also passes the tests!
15992 \begin_layout Plain Layout
15994 $NEWFANGLE -R./newfangle $TEX_SRC > ./new-newfangle
15997 \begin_layout Plain Layout
15999 export NEWFANGLE=./new-newfangle
16002 \begin_layout Plain Layout
16006 chunkref{test:run-tests}>
16014 \begin_layout Chunk
16018 \begin_layout Standard
16019 \begin_inset listings
16023 \begin_layout Plain Layout
16028 \begin_layout Plain Layout
16030 $NEWFANGLE -Rpca-test.awk $TEX_SRC | awk -f - || exit 1
16033 \begin_layout Plain Layout
16037 chunkref{test:cromulence}>
16040 \begin_layout Plain Layout
16044 chunkref{test:escapes}>
16047 \begin_layout Plain Layout
16051 chunkref{test:chunk-params}>
16059 \begin_layout Standard
16060 With a lyx-build-helper
16063 \begin_layout Chunk
16064 lyx-build-helper,language=sh
16067 \begin_layout Standard
16068 \begin_inset listings
16072 \begin_layout Plain Layout
16074 PROJECT_DIR="$LYX_r"
16077 \begin_layout Plain Layout
16079 LYX_SRC="$PROJECT_DIR/${LYX_i%.tex}.lyx"
16082 \begin_layout Plain Layout
16087 \begin_layout Plain Layout
16089 TEX_SRC="$TEX_DIR/$LYX_i"
16097 \begin_layout Section
16098 Extracting documentation
16101 \begin_layout Chunk
16105 \begin_layout Standard
16106 \begin_inset listings
16110 \begin_layout Plain Layout
16112 #python -m elyxer --css lyx.css $LYX_SRC |
16117 \begin_layout Plain Layout
16119 # iconv -c -f utf-8 -t ISO-8859-1//TRANSLIT |
16124 \begin_layout Plain Layout
16132 1>/' > www/docs/newfangle.html
16135 \begin_layout Plain Layout
16139 \begin_layout Plain Layout
16141 ( mkdir -p www/docs/newfangle && cd www/docs/newfangle &&
16146 \begin_layout Plain Layout
16148 lyx -e latex ../../../newfangle.lyx &&
16153 \begin_layout Plain Layout
16155 htlatex ../../../newfangle.tex "xhtml,fn-in" &&
16160 \begin_layout Plain Layout
16165 [0-9][0-9]* *-->//g' newfangle.html
16168 \begin_layout Plain Layout
16173 \begin_layout Plain Layout
16177 \begin_layout Plain Layout
16179 ( mkdir -p www/docs/literate && cd www/docs/literate &&
16184 \begin_layout Plain Layout
16186 lyx -e latex ../../../literate.lyx &&
16191 \begin_layout Plain Layout
16193 htlatex ../../../literate.tex "xhtml,fn-in" &&
16198 \begin_layout Plain Layout
16203 [0-9][0-9]* *-->$//g' literate.html
16206 \begin_layout Plain Layout
16216 \begin_layout Section
16217 Extracting from the command line
16220 \begin_layout Standard
16221 First you will need the tex output, then you can extract:
16224 \begin_layout Chunk
16225 lyx-build-manual,language=sh
16228 \begin_layout Standard
16229 \begin_inset listings
16233 \begin_layout Plain Layout
16235 lyx -e latex newfangle.lyx
16238 \begin_layout Plain Layout
16240 newfangle -R./newfangle newfangle.tex > ./newfangle
16243 \begin_layout Plain Layout
16245 newfangle -R./newfangle.module newfangle.tex > ./newfangle.module
16253 \begin_layout Section
16257 \begin_layout Chunk
16261 \begin_layout Standard
16262 \begin_inset listings
16266 \begin_layout Plain Layout
16271 \begin_layout Plain Layout
16276 \begin_layout Plain Layout
16281 \begin_layout Plain Layout
16286 \begin_layout Plain Layout
16291 \begin_layout Plain Layout
16296 \begin_layout Plain Layout
16301 \begin_layout Plain Layout
16305 \begin_layout Plain Layout
16310 \begin_layout Plain Layout
16315 \begin_layout Plain Layout
16320 \begin_layout Plain Layout
16325 \begin_layout Plain Layout
16330 \begin_layout Plain Layout
16335 \begin_layout Plain Layout
16349 \begin_layout Chapter
16353 \begin_layout Chunk
16354 test:chunk-params:sub,language=,params=THING;colour
16357 \begin_layout Standard
16358 \begin_inset listings
16362 \begin_layout Plain Layout
16367 \begin_layout Plain Layout
16369 a ${THING} of colour ${colour},
16372 \begin_layout Plain Layout
16374 and looking closer =<
16376 chunkref{test:chunk-params:sub:sub}(${colour})>
16384 \begin_layout Chunk
16385 test:chunk-params:sub:sub,params=colour,language=
16388 \begin_layout Standard
16389 \begin_inset listings
16393 \begin_layout Plain Layout
16395 a funny shade of ${colour}
16403 \begin_layout Chunk
16404 test:chunk-params:text,language=
16407 \begin_layout Standard
16408 \begin_inset listings
16412 \begin_layout Plain Layout
16414 What do you see? "=<
16416 chunkref{test:chunk-params:sub}(joe, red)>"
16419 \begin_layout Plain Layout
16429 \begin_layout Standard
16430 Should generate output:
16433 \begin_layout Chunk
16434 test:chunk-params:result
16437 \begin_layout Standard
16438 \begin_inset listings
16442 \begin_layout Plain Layout
16444 What do you see? "I see a joe,
16447 \begin_layout Plain Layout
16449 a joe of colour red,
16452 \begin_layout Plain Layout
16454 and looking closer a funny shade of red"
16457 \begin_layout Plain Layout
16467 \begin_layout Standard
16468 And this chunk will perform the test:
16471 \begin_layout Chunk
16475 \begin_layout Standard
16476 \begin_inset listings
16480 \begin_layout Plain Layout
16482 $NEWFANGLE -Rtest:chunk-params:result $TEX_SRC > $TMP/answer || exit 1
16485 \begin_layout Plain Layout
16487 $NEWFANGLE -Rtest:chunk-params:text $TEX_SRC > $TMP/result || exit 1
16490 \begin_layout Plain Layout
16492 passtest diff $TMP/answer $TMP/result || (echo test:chunk-params:text failed
16501 \begin_layout Chapter
16503 \begin_inset CommandInset label
16505 name "cha:Compile-log-lyx"
16512 \begin_layout Chunk
16513 ./compile-log-lyx,language=sh
16516 \begin_layout Standard
16517 \begin_inset listings
16521 \begin_layout Plain Layout
16526 \begin_layout Plain Layout
16528 # can't use gtkdialog -i, cos it uses the "source" command which ubuntu
16532 \begin_layout Plain Layout
16536 \begin_layout Plain Layout
16541 \begin_layout Plain Layout
16543 errors="/tmp/compile.log.$$"
16546 \begin_layout Plain Layout
16552 |[0-9][0-9]*: [^ ]*:
16557 \begin_layout Plain Layout
16572 \begin_layout Plain Layout
16577 \begin_layout Plain Layout
16579 sed -i -e 's/^[^ ]*[/
16604 \begin_layout Plain Layout
16609 \begin_layout Plain Layout
16614 \begin_layout Plain Layout
16619 \begin_layout Plain Layout
16621 <label>Compiler errors:</label>
16624 \begin_layout Plain Layout
16629 \begin_layout Plain Layout
16631 <tree exported_column="0">
16634 \begin_layout Plain Layout
16636 <variable>LINE</variable>
16639 \begin_layout Plain Layout
16641 <height>400</height><width>800</width>
16644 \begin_layout Plain Layout
16646 <label>File | Line | Message</label>
16649 \begin_layout Plain Layout
16652 $SELF ; "'lyxgoto $LINE</action>
16655 \begin_layout Plain Layout
16657 <input>'"cat $errors"'</input>
16660 \begin_layout Plain Layout
16665 \begin_layout Plain Layout
16670 \begin_layout Plain Layout
16672 <button><label>Build</label>
16675 \begin_layout Plain Layout
16677 <action>lyxclient -c "LYXCMD:build-program" &</action>
16680 \begin_layout Plain Layout
16685 \begin_layout Plain Layout
16687 <button ok></button>
16690 \begin_layout Plain Layout
16695 \begin_layout Plain Layout
16700 \begin_layout Plain Layout
16705 \begin_layout Plain Layout
16707 export COMPILE_DIALOG
16710 \begin_layout Plain Layout
16712 ( gtkdialog --program=COMPILE_DIALOG ; rm $errors ) &
16715 \begin_layout Plain Layout
16720 \begin_layout Plain Layout
16725 \begin_layout Plain Layout
16730 \begin_layout Plain Layout
16735 \begin_layout Plain Layout
16739 \begin_layout Plain Layout
16744 \begin_layout Plain Layout
16749 \begin_layout Plain Layout
16754 \begin_layout Plain Layout
16756 extraline=`cat $file | head -n $line | tac | sed '/^
16764 begin{lstlisting}/q' | wc -l`
16767 \begin_layout Plain Layout
16769 extraline=`expr $extraline - 1`
16772 \begin_layout Plain Layout
16774 lyxclient -c "LYXCMD:command-sequence server-goto-file-row $file $line
16775 ; char-forward ; repeat $extraline paragraph-down ; paragraph-up-select"
16778 \begin_layout Plain Layout
16783 \begin_layout Plain Layout
16787 \begin_layout Plain Layout
16792 \begin_layout Plain Layout
16794 if test -z "$COMPILE_DIALOG"
16797 \begin_layout Plain Layout
16802 \begin_layout Plain Layout