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