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