From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 8645A820A1 for ; Mon, 2 Sep 2013 18:03:56 +0200 (CEST) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of rdicosmo@gmail.com) identity=pra; client-ip=209.85.212.174; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="rdicosmo@gmail.com"; x-sender="rdicosmo@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of rdicosmo@gmail.com designates 209.85.212.174 as permitted sender) identity=mailfrom; client-ip=209.85.212.174; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="rdicosmo@gmail.com"; x-sender="rdicosmo@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-wi0-f174.google.com) identity=helo; client-ip=209.85.212.174; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="rdicosmo@gmail.com"; x-sender="postmaster@mail-wi0-f174.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AuYBAA+2JFLRVdSulGdsb2JhbABagzxLriiND4ZeFg4BAQEBBw0JCRQEJIIkAQEFMgENARQZCwEDDAEFBRgJBCEPBSABBQEBCRgTCQmHXgMPBAMFmzKPVYQoJwMKiUABBQwKjjCEXYEAA5d0gTCLC4NDQYFhgmmBbw X-IPAS-Result: AuYBAA+2JFLRVdSulGdsb2JhbABagzxLriiND4ZeFg4BAQEBBw0JCRQEJIIkAQEFMgENARQZCwEDDAEFBRgJBCEPBSABBQEBCRgTCQmHXgMPBAMFmzKPVYQoJwMKiUABBQwKjjCEXYEAA5d0gTCLC4NDQYFhgmmBbw X-IronPort-AV: E=Sophos;i="4.89,1007,1367964000"; d="scan'208";a="25475036" Received: from mail-wi0-f174.google.com ([209.85.212.174]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 02 Sep 2013 18:03:55 +0200 Received: by mail-wi0-f174.google.com with SMTP id hj3so877473wib.1 for ; Mon, 02 Sep 2013 09:03:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=qPMYVRgtOYkMqNs+5U8TZWD4kWJkKEGdgiVX+9f0ubc=; b=UKw6WLHzIL17aYxTsMJ+yXQ7qgxSEjkXbN3KGZQa69/VOzmviKfMP6dleVW5K9ekWh YiKsLJ0tpRyD19qbr78TpsFDljBXkvI+xQlFncR5NKluHHg/5/Pq8xb5eem+tAA7V2SJ i4GsAzOW+spd9UyoEmJjHFpDger+xvzN8+85q4clZdeWEmZAqeM3KVv3brmM+fe+xKXV KHE4Ew9o659CUtWkis19L1ZPqyEAK0tc5OquNZ3HSvepbb16B/3RXidmIn2v28L7vBsn tgBi5L9WrDMQo6wNy0PWbNYWEE5NkJUsKP4DxfTIq5yj1eUAnbk4/XBc/fuR7FjYBMHn Kxzg== X-Received: by 10.180.206.9 with SMTP id lk9mr14349242wic.26.1378137835192; Mon, 02 Sep 2013 09:03:55 -0700 (PDT) Received: from voyager (bny92-3-81-56-44-163.fbx.proxad.net. [81.56.44.163]) by mx.google.com with ESMTPSA id i8sm18791520wib.1.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 02 Sep 2013 09:03:54 -0700 (PDT) Sender: Roberto Di Cosmo Received: from dicosmo by voyager with local (Exim 4.80) (envelope-from ) id 1VGWbY-0008Lg-7g; Mon, 02 Sep 2013 18:03:52 +0200 Date: Mon, 2 Sep 2013 18:03:52 +0200 From: Roberto Di Cosmo To: Jonathan Protzenko Cc: caml-list@inria.fr Message-ID: <20130902160352.GA27759@voyager> References: <5224B137.8070706@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <5224B137.8070706@gmail.com> User-Agent: Mutt/1.5.20 (2009-06-14) Subject: Re: [Caml-list] Literate (sort-of) programming in OCaml Hi Jonathan, for writing course notes, many of us used in the old times a script (written in ... cough, cough .. Perl) that sort of answered your needs. I honestly do not remember who from the old Formel team wrote it for CamlLight in the first place, and who adapted it to OCaml, but you can see the old code in a message from Xavier in 1996 :-) http://caml.inria.fr/pub/old_caml_site/caml-list-ar/0651.html Here is the version I still use to produce course notes with a recent OCaml and lstlistings environments (that knows how to highlight OCaml syntax). One writes a source LaTeX file with environments like \begin{caml_example} let x = "this code will be executed, and printed out with toplevel output" \end{caml_example} \begin{caml_example*} let x = "this code will be executed, and printed out without toplevel output" \end{caml_example*} \begin{caml_eval} let x = "this code will be executed, but not printed out" \end{caml_eval} and passes it through ocaml-tex to get the LaTeX file with the results properly inlined. Ah, by the way, beware, this old code doew not do a very good job at identifying phrases, so you need to use ;; all too often in the code. Having a better (OCaml?) version with proper handling of all this would certainly be nice. -- Roberto #!/usr/bin/perl # ocaml-tex $camllight = "TERM=dumb ocaml"; $camlbegin = "\\begin{lstlisting}[escapechar=§]\n"; $camlend = "\\end{lstlisting}\n"; $camlin = ""; $camloutstart = "§\\camloutbol §"; $camloutstop = "§\\camlouteol §"; $camlblank = "\n"; $linelen = 72; $output = ""; $cut_at_blanks = 0; while ($#ARGV >= 0) { $_ = $ARGV[0]; last unless (/^-/); $linelen = $ARGV[1], shift, shift, next if (/^-n$/); $output = $ARGV[1], shift, shift, next if (/^-o$/); $camllight = $ARGV[1], shift, shift, next if (/^-caml$/); $cut_at_blanks = 1, shift, next if (/^-w$/); printf STDERR ("Unknown option '%s', ignored\n", $_); shift; } # First pass: extract the Caml phrases to evaluate open(ML, "> .input.ml") || die("Cannot create .input.ml : $!"); foreach $infile (@ARGV) { open(IN, $infile) || die("Cannot open $infile : $!"); while() { if (m/^\\begin{caml_(example|example\*|eval)}\s*$/) { while() { last if m/^\\end{caml_(example|example\*|eval)}\s*$/; print ML $_; } } } close(IN); } close(ML); # Feed the phrases to a Caml toplevel open(TOPLEVEL, "$camllight 2>&1 < .input.ml |") || die("Cannot start camllight : $!"); ; ; # skip the banner $lastread = ; $lastread =~ s/^# //; # Second pass: shuffle the TeX source and the output of the toplevel if ($output) { if ($output eq "-") { open(OUT, ">&STDOUT"); } else { open(OUT, ">$output") || die("Cannot create $output: $!"); } } foreach $infile (@ARGV) { open(IN, $infile) || die("Cannot open $infile: $!"); if (! $output) { $outfile = $infile; $outfile =~ s/\.tex$//; open(OUT, "> $outfile.ml.tex") || die("Cannot create $outfile.ml.tex: $!"); } while() { if (m/^\\begin{caml_example(\*?)}\s*$/) { $omit_answer = $1; # true if caml_example*, false if caml_example print OUT $camlbegin; $severalphrases = 0; while() { last if m/\\end{caml_example\*?}\s*$/; print OUT $camlblank if ($severalphrases); while(1) { s/\\/\\\\/g; print OUT $camlin, $_; last if m/;; *$/; $_ = ; } while ($lastread =~ s/^ //) { } while($lastread) { last if $lastread =~ s/^# //; print STDERR $lastread; if (! $omit_answer) { while (length($lastread) > $linelen) { if ($cut_at_blanks) { $cutpos = rindex($lastread, ' ', $linelen); if ($cutpos == -1) { $cutpos = $linelen; } else { $cutpos++; } } else { $cutpos = $linelen; } $line = substr($lastread, 0, $cutpos); $line =~ s/\\/\\\\/g; print OUT $camloutstart, $line, $camloutstop, "\n"; $lastread = substr($lastread, $cutpos, length($lastread) - $cutpos); } $lastread =~ s/\\/\\\\/g; print OUT $camloutstart, $lastread, $camloutstop; } $lastread = ; } $severalphrases = 1; } print OUT $camlend; } elsif (m/^\\begin{caml_eval}\s*$/) { while() { last if m/^\\end{caml_eval}\s*$/; if (m/;; *$/) { while ($lastread =~ s/^#//) { } while($lastread) { last if $lastread =~ s/^#//; print $lastread; $lastread = ; } } } } else { print OUT $_; } } close(IN); } close(TOPLEVEL); On Mon, Sep 02, 2013 at 05:39:35PM +0200, Jonathan Protzenko wrote: > Hi, > > I am currently writing a big, mostly textual document in format blah > (blah being of a course a meta-variable). Are there any tools that > would allow me to interleave OCaml code with the contents of my > document? > > More on my use-case. Creating this document requires me to perform > various subtasks, such as: > - write a code snippet in the document, > - put the code snippet in a file, > - call an external program on the file, > - paste the output into the document. > > Naturally, I wish to automate this. I could roll my own set of > commands, and parse them with OCaml, but I would be re-creating a > scripting language, and it seems to me that interleaving OCaml code > within my document would be better. Here's what I have in mind: > > > blah blah blah blah blah blah blah blah blah blah blah blah blah blah > blah blah > blah blah blah blah blah blah blah blah blah blah blah blah blah blah > blah blah > blah ... we thus write the following code ... : > > {% > let code = "" in > output code > %} > > blah blah blah ... after running the command blah ... the output is as > follows ... blah > > {% > let f = write_into_temp_file code in > let s = run_and_read "myprogram" [f] in > output s > %} > > blah blah blah blah blah blah blah blah blah blah blah blah blah blah > blah blah ... > > > Are you aware of any tool that would allow me to achieve this? > > Thanks, > > ~ jonathan > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs -- Roberto Di Cosmo ------------------------------------------------------------------ Professeur En delegation a l'INRIA PPS E-mail: roberto@dicosmo.org Universite Paris Diderot WWW : http://www.dicosmo.org Case 7014 Tel : ++33-(0)1-57 27 92 20 5, Rue Thomas Mann F-75205 Paris Cedex 13 Identica: http://identi.ca/rdicosmo FRANCE. Twitter: http://twitter.com/rdicosmo ------------------------------------------------------------------ Attachments: MIME accepted, Word deprecated http://www.gnu.org/philosophy/no-word-attachments.html ------------------------------------------------------------------ Office location: Bureau 3020 (3rd floor) Batiment Sophie Germain Avenue de France Metro Bibliotheque Francois Mitterrand, ligne 14/RER C ----------------------------------------------------------------- GPG fingerprint 2931 20CE 3A5A 5390 98EC 8BFC FCCA C3BE 39CB 12D3