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