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