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