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