]> git.lyx.org Git - lyx.git/blob - lib/examples/noweb2lyx.lyx
8b2d4b217f8cac85bcdaadc15e71a91ef6bb5bd0
[lyx.git] / lib / examples / noweb2lyx.lyx
1 #This file was created by <kayvan> Sun May  2 15:56:35 1999
2 #LyX 1.0 (C) 1995-1999 Matthias Ettrich and the LyX Team
3 \lyxformat 2.15
4 \textclass literate-article
5 \begin_preamble
6 %
7 % This relaxes the noweb constraint that chunks are
8 % never broken across pages.
9 %
10 % This is from the noweb FAQ
11 %
12 \def\nwendcode{\endtrivlist \endgroup}
13 \let\nwdocspar=\smallbreak
14 \end_preamble
15 \language default
16 \inputencoding default
17 \fontscheme default
18 \graphics default
19 \paperfontsize default
20 \spacing single 
21 \papersize Default
22 \paperpackage a4
23 \use_geometry 0
24 \use_amsmath 0
25 \paperorientation portrait
26 \secnumdepth 3
27 \tocdepth 3
28 \paragraph_separation indent
29 \defskip medskip
30 \quotes_language english
31 \quotes_times 2
32 \papercolumns 1
33 \papersides 1
34 \paperpagestyle default
35
36 \layout Title
37
38
39 \noun on 
40 noweb2lyx
41 \layout Author
42
43 Kayvan A.
44  Sylvan <kayvan@sylvan.com>
45 \layout Date
46
47 May 6, 1999
48 \layout Abstract
49
50 This document describes and implements a perl script for importing noweb
51  files into LyX
52 \layout Standard
53 \pagebreak_bottom 
54
55 \begin_inset LatexCommand \tableofcontents{}
56
57 \end_inset 
58
59
60 \layout Section
61
62 Introduction
63 \layout Standard
64
65 Since version 1.0.1, LyX now supports Literate Programming using 
66 \noun on 
67 noweb
68 \noun default 
69 .
70  This addition to LyX made it very pleasant to write programs in the literate
71  style (like this one).
72  In addition to being able to write new literate programs, it would be quite
73  useful if old 
74 \noun on 
75 noweb
76 \noun default 
77  code could be imported into LyX in some fashion.
78  That's where this program comes in.
79 \layout Standard
80
81 The purpose of 
82 \noun on 
83 noweb2lyx
84 \noun default 
85  is to convert a 
86 \noun on 
87 noweb
88 \noun default 
89  file to LyX.
90 \layout Scrap
91
92 <<noweb2lyx.in>>=
93 \newline 
94 #!@PERL@
95 \newline 
96
97 \newline 
98 # Copyright (C) 1999 Kayvan A.
99  Sylvan <kayvan@sylvan.com>
100 \newline 
101 #
102 \protected_separator 
103 You are free to use and modify this code under the terms of
104 \newline 
105 # the GNU General Public Licence version 2 or later.
106 \newline 
107 #
108 \newline 
109 #
110 \protected_separator 
111 Written with assistance from:
112 \newline 
113
114 \protected_separator 
115  Edmar Wienskoski Jr.
116  <edmar-w-jr@technologist.com>
117 \newline 
118
119 \protected_separator 
120  Amir Karger <karger@post.harvard.edu>
121 \newline 
122 #
123 \newline 
124 # $Id: noweb2lyx.lyx,v 1.1 1999/09/27 18:44:32 larsbj Exp $
125 \newline 
126 #
127 \newline 
128 # NOTE: This file was automatically generated from noweb2lyx.lyx using noweb.
129 \newline 
130 #
131 \newline 
132 <<Setup variables from user supplied args>>
133 \newline 
134 <<Subroutines>>
135 \newline 
136 <<Convert noweb to LyX>>
137 \newline 
138 @
139 \layout Section
140
141 The Noweb file defined
142 \layout Standard
143
144
145 \noun on 
146 noweb
147 \noun default 
148  file is a collection of documentation and code chunks.
149  Documentation chunks simply start with an ``@'' and have no name:
150 \layout LyX-Code
151
152 @ Here is some documentation.
153 \newline 
154 We can do arbitrary LaTeX code here.
155 \newline 
156 [...
157  blah blah blah ...]
158 \layout Standard
159
160 Code chunks look like this:
161 \layout LyX-Code
162
163 <<Name of chunk here>>=
164 \newline 
165 {...
166  code for the chunk goes here ...}
167 \newline 
168
169 \layout Standard
170
171 The ``@'' is a necessary delimiter to end the code chunk.
172  The other form that the ``@'' line takes is as follows:
173 \layout LyX-Code
174
175 <<Name of chunk here>>=
176 \newline 
177 {...
178  code for the chunk ...}
179 \newline 
180 @ %def identifier1 identifier2
181 \layout Standard
182
183 In the latter form, we are declaring to 
184 \noun on 
185 noweb
186 \noun default 
187  that this code chunk defines identifier1, identifier2, etc.
188 \layout Standard
189
190 When first tackling this problem, I spoke with members of the LyX team that
191  knew about the literate programming extensions and reLyX (the LaTeX importing
192  code).
193 \layout Standard
194
195 One of the first ideas was to extend the reLyX code to understand the 
196 \noun on 
197 noweb
198 \noun default 
199  code chunks.
200  This proved to be too hard and presents other problems
201 \begin_float footnote 
202 \layout Standard
203
204 Not the least of these problems is the fact that << is a quote in French.
205 \end_float 
206 .
207  On the other hand, it turns out that reLyX contains a very useful literal
208  quoting mechanism.
209  If the input file contains the construct
210 \layout LyX-Code
211
212
213 \backslash 
214 begin{reLyXskip}
215 \newline 
216 {...
217  LaTeX stuff ...}
218 \newline 
219
220 \backslash 
221 end{reLyXskip}
222 \layout Standard
223
224 then reLyX will copy the surrounded code to the output file verbatim.
225  Given this, the first part of the translation is easy; we simply have to
226  copy the code chunks into an intermediate file that surrounds them with
227  
228 \family typewriter 
229
230 \backslash 
231 begin{reLyXskip}
232 \family default 
233  and 
234 \family typewriter 
235
236 \backslash 
237 end{reLyXskip}
238 \family default 
239 .
240 \layout Standard
241
242 Once reLyX is done with the input file, the problem is reduced to changing
243  the code chunks from LyX's LaTeX layout to the Scrap layout.
244 \layout Standard
245
246 There is one final constraint on 
247 \noun on 
248 noweb2lyx
249 \noun default 
250 .
251  We want to be able to run it as a simple pre-processor and post-processor
252  from within reLyX.
253  We can accomplish this by setting the flags 
254 \latex latex 
255 [[pre_only]]
256 \latex default 
257  and 
258 \latex latex 
259 [[post_only]]
260 \latex default 
261  before we reach the main conversion code.
262 \layout Standard
263
264 With all that preamble out of the way, we now have the basic high-level
265  outline for our code:
266 \layout Scrap
267
268 <<Convert noweb to LyX>>=
269 \newline 
270 if (!$post_only) {
271 \newline 
272
273 \protected_separator 
274
275 \protected_separator 
276 <<Transform noweb for reLyX>>
277 \newline 
278 }
279 \newline 
280 if ((!$pre_only) && (!$post_only)) {
281 \newline 
282
283 \protected_separator 
284
285 \protected_separator 
286 <<Run reLyX on intermediate file>>
287 \newline 
288 }
289 \newline 
290 if (!$pre_only) {
291 \newline 
292
293 \protected_separator 
294
295 \protected_separator 
296 <<Fix up LyX file>>
297 \newline 
298 }
299 \newline 
300 <<Clean up>>
301 \newline 
302 @
303 \layout Section
304
305 Making a file that reLyX can process
306 \layout Standard
307
308 In this section, we present the code that performs the task of creating
309  the intermediate file that reLyX can process, using the algorithm that
310  we just outlined.
311  This algorithm is outlined in the code that follows:
312 \layout Scrap
313
314 <<Transform noweb for reLyX>>=
315 \newline 
316 <<Setup INPUT and OUTPUT>>
317 \newline 
318 inputline: while(<INPUT>)
319 \newline 
320 {
321 \newline 
322
323 \protected_separator 
324
325 \protected_separator 
326 if (/^
327 \backslash 
328 s*
329 \backslash 
330 <
331 \backslash 
332 <.*
333 \backslash 
334 >
335 \backslash 
336 >=/) { # Beginning of a noweb scrap
337 \newline 
338
339 \protected_separator 
340
341 \protected_separator 
342
343 \protected_separator 
344
345 \protected_separator 
346 <<Read in and output the noweb code chunk>>
347 \newline 
348
349 \protected_separator 
350
351 \protected_separator 
352 } elsif (/^@
353 \backslash 
354 s+(.*)/) { # Beginning of a documentation chunk
355 \newline 
356
357 \protected_separator 
358
359 \protected_separator 
360
361 \protected_separator 
362
363 \protected_separator 
364 print OUTPUT $1; # We do not need the ``@'' part
365 \newline 
366
367 \protected_separator 
368
369 \protected_separator 
370 } elsif (/
371 \backslash 
372 [
373 \backslash 
374 [.+
375 \backslash 
376 ]
377 \backslash 
378 ]/) { # noweb quoted code
379 \newline 
380
381 \protected_separator 
382
383 \protected_separator 
384
385 \protected_separator 
386
387 \protected_separator 
388 <<Perform special input quoting of [[var]]>>
389 \newline 
390
391 \protected_separator 
392
393 \protected_separator 
394 } else {
395 \newline 
396
397 \protected_separator 
398
399 \protected_separator 
400
401 \protected_separator 
402
403 \protected_separator 
404 print OUTPUT; # Just let the line pass through
405 \newline 
406
407 \protected_separator 
408
409 \protected_separator 
410 }
411 \newline 
412 }
413 \newline 
414 <<Close INPUT and OUTPUT>>
415 \newline 
416 @
417 \layout Standard
418
419 In the code above, we do some pre-processing of the noweb ``[[...]]'' construct.
420  This avoids some problems with reLyX confusing lists composed of ``[[...]]''
421  constructs.
422 \layout Scrap
423
424 <<Perform special input quoting of [[var]]>>=
425 \newline 
426 s/
427 \backslash 
428 [
429 \backslash 
430 [.+?
431 \backslash 
432 ]{2,}/{$&}/g;
433 \newline 
434 print OUTPUT;
435 \newline 
436 @
437 \layout Standard
438
439 While reading in the 
440 \latex latex 
441 [[INPUT]]
442 \latex default 
443  file, once we have identified a 
444 \noun on 
445 noweb
446 \noun default 
447  code chunk, we transform it into a form that is usable by reLyX.
448 \layout Scrap
449
450 <<Read in and output the noweb code chunk>>= 
451 \newline 
452 <<Save the beginning of the scrap to savedScrap>>
453 \newline 
454 <<Concatenate the rest of the scrap>>
455 \newline 
456 <<print out the scrap in a reLyXskip block>>
457 \newline 
458 @
459 \layout Subsection
460
461 File input and output for the pre-processing step
462 \layout Standard
463
464 In 
465 \noun on 
466 noweb2lyx
467 \noun default 
468 , we will use 
469 \latex latex 
470 [[INPUT]]
471 \latex default 
472  and 
473 \latex latex 
474 [[OUTPUT]]
475 \latex default 
476  to read and write files.
477  In the code fragment above, we need to read from the input file and write
478  to a file that will be later transformed by reLyX.
479  If we are being called only to pre-process the input file, then there is
480  no need to create a temporary file.
481 \layout Scrap
482
483 <<Setup INPUT and OUTPUT>>=
484 \newline 
485 if ($pre_only) {
486 \newline 
487
488 \protected_separator 
489
490 \protected_separator 
491 &setup_files($input_file, $output_file);
492 \newline 
493 } else {
494 \newline 
495
496 \protected_separator 
497
498 \protected_separator 
499 $relyx_file = "temp$$";
500 \newline 
501
502 \protected_separator 
503
504 \protected_separator 
505 &setup_files($input_file, $relyx_file);
506 \newline 
507 }
508 \newline 
509 @
510 \layout Standard
511
512 This code uses a small perl subroutine, 
513 \latex latex 
514 [[setup_files]]
515 \latex default 
516 , which we define below:
517 \layout Scrap
518
519 <<Subroutines>>=
520 \newline 
521 sub setup_files {
522 \newline 
523
524 \protected_separator 
525
526 \protected_separator 
527 my($in, $out) = @_;
528 \newline 
529
530 \protected_separator 
531
532 \protected_separator 
533 open(INPUT, "<$in") || die "Can not read $in: $!
534 \backslash 
535 n";
536 \newline 
537
538 \protected_separator 
539
540 \protected_separator 
541 open(OUTPUT, ">$out") || die "Can not write $out: $!
542 \backslash 
543 n";
544 \newline 
545 }
546 \newline 
547 @ %def setup_files 
548 \protected_separator 
549
550 \protected_separator 
551
552 \layout Subsection
553
554 Reading in the 
555 \noun on 
556 noweb
557 \noun default 
558  scrap
559 \layout Standard
560
561 After we see the beginning of the scrap, we need to read in and save the
562  rest of the scrap for output.
563 \layout Scrap
564
565 <<Save the beginning of the scrap to savedScrap>>=
566 \newline 
567 $savedScrap = $_;
568 \newline 
569 $endLine = "";
570 \newline 
571 @
572 \layout Scrap
573
574 <<Concatenate the rest of the scrap>>=
575 \newline 
576 scrapline: while (<INPUT>) {
577 \newline 
578
579 \protected_separator 
580
581 \protected_separator 
582 last scrapline if /^@
583 \backslash 
584 s+/;
585 \newline 
586
587 \protected_separator 
588
589 \protected_separator 
590 $savedScrap .= $_;
591 \newline 
592 };
593 \newline 
594 switch: {
595 \newline 
596
597 \protected_separator 
598
599 \protected_separator 
600 if (/^@
601 \backslash 
602 s+$/) {$savedScrap .= $_; last switch; }
603 \newline 
604
605 \protected_separator 
606
607 \protected_separator 
608 if (/^@
609 \backslash 
610 s+%def.*$/) {$savedScrap .= $_; last switch; }
611 \newline 
612
613 \protected_separator 
614
615 \protected_separator 
616 if (/^@
617 \backslash 
618 s+(.*)$/) {$savedScrap .= "@
619 \backslash 
620 n"; $endLine = "$1
621 \backslash 
622 n"; }
623 \newline 
624 }
625 \newline 
626 @
627 \layout Subsection
628
629 Printing out the scrap
630 \layout Standard
631
632 The final piece of the first pass of the conversion is done by this code.
633 \layout Scrap
634
635 <<print out the scrap in a reLyXskip block>>=
636 \newline 
637 print OUTPUT "
638 \backslash 
639
640 \backslash 
641 begin{reLyXskip}
642 \backslash 
643 n";
644 \newline 
645 print OUTPUT $savedScrap;
646 \newline 
647 print OUTPUT "
648 \backslash 
649
650 \backslash 
651 end{reLyXskip}
652 \backslash 
653 n
654 \backslash 
655 n";
656 \newline 
657 print OUTPUT "$endLine";
658 \newline 
659 @
660 \layout Standard
661
662 Finally, we need to close the 
663 \latex latex 
664 [[INPUT]]
665 \latex default 
666  and 
667 \latex latex 
668 [[OUTPUT]]
669 \latex default 
670  files.
671 \layout Scrap
672
673 <<Close INPUT and OUTPUT>>=
674 \newline 
675 close(INPUT);
676 \newline 
677 close(OUTPUT);
678 \newline 
679 @
680 \layout Section
681
682 Running reLyX
683 \layout Standard
684
685 In this section, we describe and implement the code that runs reLyX on the
686  intermediate file 
687 \latex latex 
688 [[relyx_file]]
689 \latex default 
690 .
691  
692 \layout Subsection
693
694 Selecting the document class
695 \layout Standard
696
697 In order to run reLyX, we need to know the article class of the input document
698  (to choose the corresponding literate document layout).
699  For this, we need to parse the intermediate file.
700 \layout Scrap
701
702 <<Run reLyX on intermediate file>>=
703 \newline 
704 <<Parse for document class>>
705 \newline 
706 <<Run reLyX with document class>>
707 \newline 
708 @
709 \layout Standard
710
711 In the code below, you'll see a strange regular expression to search for
712  the document class.
713  The reason for this kludge is that without it, we can't run 
714 \noun on 
715 noweb2lyx
716 \noun default 
717  on the 
718 \emph on 
719 noweb2lyx.nw
720 \emph default 
721  file that is generated by LyX
722 \begin_float footnote 
723 \layout Standard
724
725 reLyX searches for 
726 \backslash 
727
728 \backslash 
729 doc
730 \latex latex 
731 {}
732 \latex default 
733 ument
734 \latex latex 
735 {}
736 \latex default 
737 class and gets confused, so we have to obfuscate it slightly.
738 \end_float 
739 .
740  With the regular expression as it is, we can actually run 
741 \noun on 
742 noweb2lyx
743 \noun default 
744  on itself and a produce a quite reasonable LyX file.
745 \layout Scrap
746
747 <<Parse for document class>>=
748 \newline 
749 open(INPUT, "<$relyx_file") ||
750 \newline 
751
752 \protected_separator 
753
754 \protected_separator 
755 die "Can not read $relyx_file: $!
756 \backslash 
757 n";
758 \newline 
759 $class = "article"; # default if none found
760 \newline 
761 parse: while(<INPUT>) {
762 \newline 
763
764 \protected_separator 
765
766 \protected_separator 
767 if (/
768 \backslash 
769
770 \backslash 
771 docu[m]entclass{(.*)}/) {
772 \newline 
773
774 \protected_separator 
775
776 \protected_separator 
777
778 \protected_separator 
779
780 \protected_separator 
781 $class = $1;
782 \newline 
783
784 \protected_separator 
785
786 \protected_separator 
787
788 \protected_separator 
789
790 \protected_separator 
791 last parse;
792 \newline 
793
794 \protected_separator 
795
796 \protected_separator 
797 }
798 \newline 
799 }
800 \newline 
801 close(INPUT);
802 \newline 
803 @
804 \layout Subsection
805
806 Running reLyX with the corresponding literate document layout
807 \layout Standard
808
809 Now that we know what the document class ought to be, we do:
810 \layout Scrap
811
812 <<Run reLyX with document class>>= 
813 \newline 
814 $doc_class = "literate-" .
815  $class;
816 \newline 
817 die "reLyX returned non-zero: $!
818 \backslash 
819 n"
820 \newline 
821
822 \protected_separator 
823
824 \protected_separator 
825 if (system("reLyX -c $doc_class $relyx_file"));
826 \newline 
827 @
828 \layout Standard
829
830 reLyX performs the main bulk of the translation work.
831  Note that if the ``literate-
832 \emph on 
833 class
834 \emph default 
835 '' document layout is not found, then reLyX will fail with an error.
836  In that case, you may need to modify your 
837 \noun on 
838 noweb
839 \noun default 
840  input file to a supported document type.
841 \layout Section
842
843 Fixing the reLyX output
844 \layout Standard
845
846 We need to perform some post-processing of what reLyX produces in order
847  to have the best output for our literate document.
848  The outline of the post-processing steps are:
849 \layout Scrap
850
851 <<Fix up LyX file>>=
852 \newline 
853 <<Setup INPUT and OUTPUT for the final output>>
854 \newline 
855 line: while(<INPUT>)
856 \newline 
857 {
858 \newline 
859
860 \protected_separator 
861
862 \protected_separator 
863 <<Fix code chunks in latex layout>>
864 \newline 
865
866 \protected_separator 
867
868 \protected_separator 
869 <<Fix [[var]] noweb construct>>
870 \newline 
871
872 \protected_separator 
873
874 \protected_separator 
875 print OUTPUT; # default
876 \newline 
877
878 \newline 
879 <<Close INPUT and OUTPUT>>
880 \newline 
881 @
882 \layout Standard
883
884 Note that in the perl code that is contained in the 
885 \latex latex 
886 [[while(<INPUT>)]]
887 \latex default 
888  loop above, the perl construct 
889 \latex latex 
890 [[next line]]
891 \latex default 
892  is sufficient to restart the loop.
893  We can use this construct to do some relatively complex parsing of the
894  reLyX generated file.
895 \layout Subsection
896
897 File input and output for the post-processing
898 \layout Standard
899
900 Setting up the 
901 \latex latex 
902 [[INPUT]]
903 \latex default 
904  and 
905 \latex latex 
906 [[OUTPUT]]
907 \latex default 
908  is taken care of by this code:
909 \layout Scrap
910
911 <<Setup INPUT and OUTPUT for the final output>>=
912 \newline 
913 if ($post_only) {
914 \newline 
915
916 \protected_separator 
917
918 \protected_separator 
919 &setup_files("$input_file", "$output_file");
920 \newline 
921 } else {
922 \newline 
923
924 \protected_separator 
925  &setup_files("$relyx_file.lyx", "$output_file");
926 \newline 
927 }
928 \newline 
929 @
930 \layout Subsection
931
932 Making sure the code chunks are in the Scrap layout
933 \layout Standard
934
935 Now, as we outlined before, the final step is transforming the code-chunks
936  which have been put into a LaTeX layout by LyX into the scrap layout.
937 \layout Scrap
938
939 <<Fix code chunks in latex layout>>=
940 \newline 
941 if (/
942 \backslash 
943
944 \backslash 
945 latex latex/) { # Beginning of some latex code
946 \newline 
947
948 \protected_separator 
949
950 \protected_separator 
951 if (($line = <INPUT>) =~ /^
952 \backslash 
953 s*<</) { # code scrap
954 \newline 
955
956 \protected_separator 
957
958 \protected_separator 
959  
960 \protected_separator 
961 <<Transform this chunk into layout scrap>>
962 \newline 
963
964 \protected_separator 
965
966 \protected_separator 
967 } else {
968 \newline 
969
970 \protected_separator 
971
972 \protected_separator 
973
974 \protected_separator 
975
976 \protected_separator 
977 # print the 
978 \backslash 
979 latex latex line + next line
980 \newline 
981
982 \protected_separator 
983
984 \protected_separator 
985
986 \protected_separator 
987
988 \protected_separator 
989 print OUTPUT "$_$line";
990 \newline 
991
992 \protected_separator 
993
994 \protected_separator 
995 }
996 \newline 
997
998 \protected_separator 
999
1000 \protected_separator 
1001 next line;
1002 \newline 
1003 }
1004 \newline 
1005 @
1006 \layout Standard
1007
1008 When we are sure that we are in a code chunk, we must read in the rest of
1009  the code chunk and output a scrap layout for it:
1010 \layout Scrap
1011
1012 <<Transform this chunk into layout scrap>>=
1013 \newline 
1014 $savedScrap = "
1015 \backslash 
1016
1017 \backslash 
1018 layout Scrap
1019 \backslash 
1020 n
1021 \backslash 
1022 n$line";
1023 \newline 
1024 codeline: while (<INPUT>) {
1025 \newline 
1026
1027 \protected_separator 
1028
1029 \protected_separator 
1030 $savedScrap .= $_;
1031 \newline 
1032
1033 \protected_separator 
1034
1035 \protected_separator 
1036 last codeline if /^@
1037 \backslash 
1038 s+/;
1039 \newline 
1040 };
1041 \newline 
1042 print OUTPUT $savedScrap;
1043 \newline 
1044 <<Slurp up to the end of the latex layout>>
1045 \newline 
1046 @
1047 \layout Standard
1048
1049 Okay, now we just need to eat the rest of the latex layout.
1050  There should only be a few different types of lines for us to match:
1051 \layout Scrap
1052
1053 <<Slurp up to the end of the latex layout>>=
1054 \newline 
1055 slurp: while (<INPUT>) {
1056 \newline 
1057
1058 \protected_separator 
1059
1060 \protected_separator 
1061 last slurp if /
1062 \backslash 
1063
1064 \backslash 
1065 latex /;
1066 \newline 
1067
1068 \protected_separator 
1069
1070 \protected_separator 
1071 next slurp if /
1072 \backslash 
1073
1074 \backslash 
1075 newline/;
1076 \newline 
1077
1078 \protected_separator 
1079
1080 \protected_separator 
1081 next slurp if /^
1082 \backslash 
1083 s*$/;
1084 \newline 
1085
1086 \protected_separator 
1087
1088 \protected_separator 
1089 warn "confused by line: $_";
1090 \newline 
1091 }
1092 \newline 
1093 @
1094 \layout Subsection
1095
1096 Taking care of the 
1097 \noun on 
1098 noweb
1099 \noun default 
1100  
1101 \emph on 
1102 [[quoted code]]
1103 \emph default 
1104  construct
1105 \layout Standard
1106
1107
1108 \noun on 
1109 noweb
1110 \noun default 
1111  allows the user to use a special code quoting mechanism in documentation
1112  chunks.
1113  Fixing this ``[[quoted-code]]'' 
1114 \noun on 
1115 noweb
1116 \noun default 
1117  syntax means putting the ``[[quoted-code]]'' in a LaTeX layout in the LyX
1118  file.
1119  Otherwise, LyX will backslash-quote the brackets, creating ugly output.
1120  The quoted-code is transformed by 
1121 \noun on 
1122 noweb
1123 \noun default 
1124  when it generates the final LaTeX code.
1125 \layout Scrap
1126
1127 <<Fix [[var]] noweb construct>>=
1128 \newline 
1129 if (/
1130 \backslash 
1131 [
1132 \backslash 
1133 [.+
1134 \backslash 
1135 ]
1136 \backslash 
1137 ]/) { # special code for [[var]]
1138 \newline 
1139
1140 \protected_separator 
1141
1142 \protected_separator 
1143 s/
1144 \backslash 
1145 [
1146 \backslash 
1147 [.+?
1148 \backslash 
1149 ]{2,}/
1150 \backslash 
1151 n
1152 \backslash 
1153
1154 \backslash 
1155 latex latex
1156 \backslash 
1157 n$&
1158 \backslash 
1159 n
1160 \backslash 
1161
1162 \backslash 
1163 latex default
1164 \backslash 
1165 n/g;
1166 \newline 
1167
1168 \protected_separator 
1169
1170 \protected_separator 
1171 print OUTPUT;
1172 \newline 
1173
1174 \protected_separator 
1175
1176 \protected_separator 
1177 next line;
1178 \newline 
1179 }
1180 \newline 
1181 @
1182 \layout Section
1183
1184 Cleaning up intermediate files
1185 \layout Standard
1186
1187 The cleanup code is very simple:
1188 \layout Scrap
1189
1190 <<Clean up>>=
1191 \newline 
1192 system("rm -f $relyx_file*") unless ($post_only || $pre_only);
1193 \newline 
1194 @
1195 \layout Section
1196
1197 User supplied arguments
1198 \layout Standard
1199
1200 The 
1201 \noun on 
1202 noweb2lyx
1203 \noun default 
1204  script understands two arguments, input-file and output-file.
1205  It is also set up to be used internally by reLyX to pre-process or postprocess
1206  files in the import pipeline.
1207 \layout Scrap
1208
1209 <<Setup variables from user supplied args>>=
1210 \newline 
1211 &usage() if ($#ARGV < 1); # zero or one argument 
1212 \newline 
1213 if ($ARGV[0] eq "-pre") {
1214 \newline 
1215
1216 \protected_separator 
1217
1218 \protected_separator 
1219 &usage unless ($#ARGV == 2);
1220 \newline 
1221
1222 \protected_separator 
1223
1224 \protected_separator 
1225 $input_file = $ARGV[1]; $output_file = $ARGV[2]; $pre_only = 1;
1226 \newline 
1227 } elsif ($ARGV[0] eq "-post") {
1228 \newline 
1229
1230 \protected_separator 
1231
1232 \protected_separator 
1233 &usage unless ($#ARGV == 2);
1234 \newline 
1235
1236 \protected_separator 
1237
1238 \protected_separator 
1239 $input_file = $ARGV[1]; $output_file = $ARGV[2]; $post_only = 1;
1240 \newline 
1241 } else {
1242 \newline 
1243
1244 \protected_separator 
1245
1246 \protected_separator 
1247 &usage unless ($#ARGV == 1);
1248 \newline 
1249
1250 \protected_separator 
1251
1252 \protected_separator 
1253 $input_file = $ARGV[0];
1254 \protected_separator 
1255 $output_file = $ARGV[1];
1256 \newline 
1257
1258 \protected_separator 
1259
1260 \protected_separator 
1261 $pre_only = 0; $post_only = 0;
1262 \newline 
1263 }
1264 \newline 
1265 @ %def input_file output_file pre_only post_only
1266 \layout Scrap
1267
1268 <<Subroutines>>=
1269 \newline 
1270 sub usage() {
1271 \newline 
1272
1273 \protected_separator 
1274
1275 \protected_separator 
1276 print "Usage: noweb2lyx [-pre | -post] input-file output-file
1277 \newline 
1278
1279 \newline 
1280 If -pre is specified, only pre-processes the input-file for reLyX.
1281 \newline 
1282 Similarly, in the case of -post, post-processes reLyX output.
1283 \newline 
1284 In case of bugs, Email Kayvan Sylvan <kayvan
1285 \backslash 
1286 @sylvan.com>.
1287 \backslash 
1288 n";
1289 \newline 
1290
1291 \protected_separator 
1292
1293 \protected_separator 
1294 exit;
1295 \newline 
1296 }
1297 \newline 
1298 @ %def usage
1299 \layout Section
1300
1301 Generating the 
1302 \noun on 
1303 noweb2lyx
1304 \noun default 
1305  script
1306 \layout Standard
1307
1308 The noweb2lyx script can be tangled from LyX if you set 
1309 \family typewriter 
1310
1311 \backslash 
1312 build_command
1313 \family default 
1314  to call a generic script that always extracts a scrap named 
1315 \family typewriter 
1316 build-script
1317 \family default 
1318  and executes it.
1319  Here is an example of such a script:
1320 \layout LyX-Code
1321
1322 #!/bin/sh
1323 \newline 
1324 notangle -Rbuild-script $1 | sh
1325 \layout Scrap
1326
1327 <<build-script>>=
1328 \newline 
1329 PREFIX=/usr
1330 \newline 
1331 notangle -Rnoweb2lyx.in noweb2lyx.nw > noweb2lyx.in
1332 \newline 
1333 sed -e "s=@PERL@=$PREFIX/bin/perl=" noweb2lyx.in > noweb2lyx
1334 \newline 
1335 chmod +x noweb2lyx
1336 \newline 
1337 @
1338 \layout Section*
1339 \pagebreak_top 
1340 Macros
1341 \layout Standard
1342
1343
1344 \latex latex 
1345
1346 \backslash 
1347 nowebchunks
1348 \layout Section*
1349
1350 Identifiers
1351 \layout Standard
1352
1353
1354 \latex latex 
1355
1356 \backslash 
1357 nowebindex
1358 \the_end