<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mathematical Pamphlet &#187; LaTeX</title>
	<atom:link href="http://www.kennknowles.com/blog/category/latex/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kennknowles.com/blog</link>
	<description>Mathematics, Haskell, and little bit of Linux</description>
	<lastBuildDate>Sat, 12 Jul 2008 20:17:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using HaXml to make a PDF slideshow from an Inkscape SVG</title>
		<link>http://www.kennknowles.com/blog/2008/04/20/using-haxml-to-make-a-pdf-slideshow-from-an-inkscape-svg/</link>
		<comments>http://www.kennknowles.com/blog/2008/04/20/using-haxml-to-make-a-pdf-slideshow-from-an-inkscape-svg/#comments</comments>
		<pubDate>Sun, 20 Apr 2008 09:01:21 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[gournal]]></category>
		<category><![CDATA[HaXml]]></category>
		<category><![CDATA[Inkscape]]></category>
		<category><![CDATA[jarnal]]></category>
		<category><![CDATA[note-taking]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[slide]]></category>
		<category><![CDATA[SVG]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[xournal]]></category>

		<guid isPermaLink="false">http://www.kennknowles.com/blog/2008/04/20/using-haxml-to-make-a-pdf-slideshow-from-an-inkscape-svg/</guid>
		<description><![CDATA[I recently got a tablet to input handwritten math for slideshow presentations, but instead of using a note-taking program (Jarnal,
Xournal,
Gournal) I decided that I wanted the full power of image manipulation of a program like Gimp or Inkscape.  Neither of these, though, has the level of support for multi-page documents that you find in [...]]]></description>
			<content:encoded><![CDATA[<p>I recently got a tablet to input handwritten math for slideshow presentations, but instead of using a note-taking program (<a href="http://www.dklevine.com/general/software/tc1000/jarnal.htm">Jarnal</a>,
<a href="http://xournal.sourceforge.net/">Xournal</a>,
<a href="http://www.adebenham.com/gournal/">Gournal</a>) I decided that I wanted the full power of image manipulation of a program like <a href="http://www.gimp.org/">Gimp</a> or <a href="http://www.inkscape.org/">Inkscape</a>.  Neither of these, though, has the level of support for multi-page documents that you find in note-taking software.  But Inkscape uses SVG as its native file format, so I wrote this Haskell script to transform the layers of an Inkscape SVG file into the slides of a PDF presentation.  I use the
<a href="http://www.cs.york.ac.uk/fp/HaXml/">HaXml</a> library to manipulate the SVG, the Inkscape command-line interface to convert each page to PDF, and <a href="http://www.pdfhacks.com/pdftk/">pdftk</a> to glue the whole thing back together.</p>

<p><a href='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/Slide001.svg' title='slide001.svg'><img width='200' src='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/slide001.png' alt='slide001.png' /></a>
<a href='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/Slide002.svg' title='slide002.png'><img width='200' src='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/slide002.png' alt='slide002.png' /></a></p>

<p><a href='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/Slide003.svg' title='slide003.png'><img width='200' src='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/slide003.png' alt='slide003.png' /></a>
<a href='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/Slide004.svg' title='slide004.png'><img width='200' src='http://www.kennknowles.com/blog/wp-content/uploads/2008/04/slide004.png' alt='slide004.png' /></a></p>

<p>As usual, this post is a literate Haskell file, so you can try it out by saving it to <code>Inkscape.lhs</code>, compiling with <code>ghc --make Inkscape</code>, grabbing the <a href="http://www.kennknowles.com/blog/wp-content/uploads/2008/04/demo.svg">source file for the images above</a>, and running <code>./Inkscape &lt; demo.svg</code>.  The output will appear in <code>Slides.pdf</code> (and your directory will be polluted with temp files, so be aware).
<span id="more-53"></span></p>

<p>For the record, multi-page documents have been on the Inkscape feature
request tracker for many versions, so I presume it is a significant
change.  I <em>do</em> grok C and C++, thanks to the legacy-oriented
education system, but take little enough pleasure from them that I
would rather hack around the issue in Haskell.</p>

<pre>
> import Text.XML.HaXml
> import Text.XML.HaXml.Pretty
> import Text.XML.HaXml.Posn
> import Text.PrettyPrint.HughesPJ
> import Text.Printf
> import Data.List
> import System.IO
> import System.Cmd
</pre>

<p>HaXml is based on a combinator library for <code>CFilter</code>s to filter, search, output, etc XML content.  It is a little crufty in some ways &#8212; many datatypes are transpararent, and you have to do a lot of your own set up and tear down.  The expected way to use it seems to be via <code>processXmlWith :: CFilter -&gt; IO ()</code> which is not sufficient for today&#8217;s task.  The Hackage documentation pointed to an old version of the API, so I used the current version of the source code for documentation.  I&#8217;d love any criticism like &#8220;you didn&#8217;t have to do X&#8221; or &#8220;here is an easier, safer way to do Y&#8221;.</p>

<p>I couldn&#8217;t think of a better way to narrate this code, so I&#8217;ll start with <code>main</code> for a high-level read, and then later fill in all the helper functions. Naturally we start with a call to <code>xmlParse</code>; the <code>"-"</code> is a required filename for error reporting.</p>

<pre>
> main = do input <- getContents
>           let xml = xmlParse "-" input
</pre>

<p>Then I grab the names of all the layer objects in the order they appear in the file, except for the special layer &#8220;Background&#8221; which I&#8217;ll include behind every slide.  The call to <code>verbatim</code> spits them out as <code>String</code>s instead of XML <code>Content</code>, and the <code>"-"</code> is yet another required filename for error reporting.</p>

<pre>
>           let names = delete "Background" 
>                       $ map verbatim 
>                       $ filterElem "-" getLayerNames
>                       $ xmlElem 
>                       $ xml
>           putStrLn $ "Making slides from layers:" 
>                        ++ concatMap ("\n\t"++) names ++ "\n"
</pre>

<p>Then for each layer, make a new version of the file with just that layer visible.</p>

<pre>
>           let outXmls = map (flip selectLayer xml) names
>               usedSlides = take (length names) slideNames
>           mapM_ (uncurry writeFile) 
>                 (zip (map (++".svg") slideNames) 
>                      (map (renderStyle xmlStyle . document) outXmls))
</pre>

<p>And some shell scripting done in Haskell.  I didn&#8217;t even try to find a scripting library or anything to e.g. prevent me from building a malformed command.</p>

<pre>
>           mapM_ (\slide -> do 
>                    system $ "inkscape --export-text-to-path --export-pdf='" 
>                             ++ slide ++ ".pdf' '" ++ slide ++ ".svg'")
>                 usedSlides
>           
>           system $ "pdftk " 
>                      ++ concat (intersperse " " (map (++".pdf") usedSlides)) 
>                      ++ " cat output Slides.pdf"
</pre>

<p>So now to the little details:</p>

<h2>Grabbing the layer names</h2>

<p>Here is the first helper I wrote, wrapping HaXml&#8217;s <code>attrval</code> for a common case.  This filter returns every tag whose <code>attr</code> attribute has the string value <code>val</code>.</p>

<pre>
> matchAttrString :: String -> String -> CFilter i
> matchAttrString attr val = attrval (attr, AttValue [Left val])
</pre>

<p>The next helper is one that maps a tag to its attribute value, otherwise discards anything else it sees.  The HaXml function <code>iffind</code> will pass the <code>attr</code> attribute value of a tag to <code>literal</code> which just returns it.  If the attribute isn&#8217;t found, or the XML data isn&#8217;t a tag, then <code>none</code> will discard it.</p>

<pre>
> showAttr :: String -> CFilter i
> showAttr attr = iffind attr literal none
</pre>

<p>The Inkscape layers are contained in <code>&lt;g inkscape:groupmode='layer' ...&gt;</code> tags.  The name of the layer is in the <code>inkscape:label</code> attribute.  I imagine this will change as Inkscape evolves.  The <code>o</code> is the composition operator for <code>CFilter</code>s.</p>

<pre>
> isLayer = matchAttrString "inkscape:groupmode" "layer"
> getLayerNames = showAttr "inkscape:label" `o` isLayer `o` children
</pre>

<h2>Isolating the layers</h2>

<p>Again proceeding from the outside of my program inwards, a layer is isolated with this helper, using <code>iffind</code> to match either the layer name or the layer &#8220;Background&#8221; which I&#8217;m going to leave in all the output files.  The final <code>keep</code> argument to <code>iffind</code> says to keep
parts of the XML that don&#8217;t have the <code>"inkscape:label"</code> attribute.</p>

<pre>
> selectLayer :: String -> Document Posn -> Document Posn
> selectLayer layer doc = onContent "-" (chip (visible `o` onlyLayer)) doc
>     where onlyLayer = iffind "inkscape:label" layerOrBG keep
>           layerOrBG l = if l == layer || l == "Background" then keep else none
</pre>

<p>In writing <code>visible</code> I was surprised that there was a combinator to set <em>all</em> attributes for a tag, but none to set a single attribute.</p>

<pre>
> visible = setAttr "style" "display:inline"
> setAttr key val (CElem (Elem tag attrs cs) i) = [CElem (Elem tag newattrs cs) i]
>     where newattrs = (key, AttValue [Left val]) : filter ((/= key) . fst) attrs
> setAttr key val other = [other] -- Hackish?
</pre>

<p>As I mentioned before, there is no way that I see to directly apply this filter to an XML file using HaXml.  The type <code>CFilter = Content -&gt; [Content]</code> needs wrapping to apply to an XML <code>Element</code> directly. Notice how I have to pass in a <code>file</code> for error reporting; it feels like I&#8217;m doing things I&#8217;m not supposed to.</p>

<pre>
> filterElem :: FilePath -> CFilter Posn -> Element Posn -> [Content Posn]
> filterElem file f e = f (CElem e (posInNewCxt file Nothing))

> xmlElem (Document _ _ e _) = e
</pre>

<p>And now the function to actually apply a filter to an XML document.  This is straight from the body of <code>processXmlWith</code> in the HaXml source, with <code>filterElem</code> pulled out.</p>

<pre>
> onContent :: FilePath -> (CFilter Posn) -> Document Posn -> Document Posn
> onContent file filter (Document p s e m) =
>     case filterElem file filter e of
>              [CElem e' _] -> Document p s e' m
>              []           -> error "produced no output"
>              _            -> error "produced more than one output"
</pre>

<h2>Bits and pieces</h2>

<p>I also used a modified style for the HughesPJ pretty printer</p>

<pre>
> xmlStyle = style { mode = LeftMode }
</pre>

<p>And a big list of slide names with three digits, for this one-off job.  Better would be to use an API for generating fresh temporary files.</p>

<pre>
> slideNumbers = map (printf "%03d") ([1..999] :: [Int])
> slideNames = map ("Slide"++) slideNumbers
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2008/04/20/using-haxml-to-make-a-pdf-slideshow-from-an-inkscape-svg/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Slideshow presentations in LaTeX</title>
		<link>http://www.kennknowles.com/blog/2007/03/21/slideshow-presentations-in-latex/</link>
		<comments>http://www.kennknowles.com/blog/2007/03/21/slideshow-presentations-in-latex/#comments</comments>
		<pubDate>Wed, 21 Mar 2007 20:25:27 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[Beamer]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Powerdot]]></category>
		<category><![CDATA[Prosper]]></category>
		<category><![CDATA[slideshow]]></category>

		<guid isPermaLink="false">http://www.kennknowles.org/blog/2007/03/21/slideshow-presentations-in-latex/</guid>
		<description><![CDATA[There&#8217;s a really nice presentation package for LaTeX called powerdot; I moved to it directly from Prosper &#8211; I never got around to using Beamer or HA-Prosper &#8211; and it rules.   But it requires versions of auxiliary bits that are not in the latest teTeX distribution, so I needed to have my local [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a really nice presentation package for LaTeX called <a href="http://www.ctan.org/tex-archive/macros/latex/contrib/powerdot/ ">powerdot</a>; I moved to it directly from Prosper &#8211; I never got around to using Beamer or HA-Prosper &#8211; and it rules.  <span id="more-15"></span> But it requires versions of auxiliary bits that are not in the latest teTeX distribution, so I needed to have my local versions override the official ones (I was a bit frightened of actually overwriting the texmf directory, since I am on many deadlines)</p>

<p>Kind of lame, but it took me a minute to figure out:  To get TeX to search different directories, you need to set the <code>TEXINPUTS</code> or <code>TEXINPUTS_latex</code> to a normal colon-separated path.  That Kpathsea is its own library shows how much higher-level modern languages are!</p>

<p>In my poking about I also discovered that teTeX is no longer updated, and it seems TeXLive may be the most &#8220;modern&#8221; tex distribution.  It appears to have the relatively insane distribution method of downloading a DVD image and mounting it locally, probably related to being kind of Windows-centric, but also downright weird and old-fashioned (who installs from anything but the net?).   The XeTeX program looks nice for being able to input unicode to TeX, something that I failed to figure out a couple of years ago.  Since I have various TeX-involved deadlines, I won&#8217;t be trying anything new for a couple of weeks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2007/03/21/slideshow-presentations-in-latex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LaTeX editing tools</title>
		<link>http://www.kennknowles.com/blog/2007/02/28/latex-editing-tools/</link>
		<comments>http://www.kennknowles.com/blog/2007/02/28/latex-editing-tools/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 20:13:41 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[editors]]></category>

		<guid isPermaLink="false">http://www.kennknowles.org/blog/2007/02/28/latex-editing-tools/</guid>
		<description><![CDATA[Editing LaTeX is very nice with WhizzyTeX but I seem to frequently get version/program conflicts where one or more of emacs/whizzytex/advi are unhappy.  So I came across a variety of emacs helpers for writing TeX with a little less pain; I have yet to try them out so this list is as much for [...]]]></description>
			<content:encoded><![CDATA[<p>Editing LaTeX is very nice with <a href="http://pauillac.inria.fr/whizzytex/">WhizzyTeX</a> but I seem to frequently get version/program conflicts where one or more of emacs/whizzytex/advi are unhappy.  So I came across a variety of emacs helpers for writing TeX with a little less pain; I have yet to try them out so this list is as much for me as anyone else:</p>

<ul>
  <li><a href="http://pauillac.inria.fr/whizzytex/">WhizzyTeX</a> &#8211; realtime preview of TeX in a separate window.  This synergizes the idea of GUI word processing (the important part of WYSIWYG is realtime visualization) and markup languages (which beat all GUI&#8217;s hands-down in terms of ease of editing complex documents).</li>
  <li><a href="http://preview-latex.sourceforge.net/">preview-latex</a> &#8211; has an &#8220;edit&#8221; mode where you hack latex, then when you leave edit mode it renders a little preview.  I haven&#8217;t tried it in depth yet.</li>
  <li><a href="http://sunsite.auc.dk/auctex/">AucTex</a> &#8211; A nice LaTeX major mode (or so I hear)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2007/02/28/latex-editing-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presenting semi-formal proofs in LaTeX</title>
		<link>http://www.kennknowles.com/blog/2007/02/05/presenting-semi-formal-proofs-in-latex/</link>
		<comments>http://www.kennknowles.com/blog/2007/02/05/presenting-semi-formal-proofs-in-latex/#comments</comments>
		<pubDate>Mon, 05 Feb 2007 20:12:03 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[proofs]]></category>

		<guid isPermaLink="false">http://www.kennknowles.org/blog/2007/02/05/presenting-semi-formal-proofs-in-latex/</guid>
		<description><![CDATA[I&#8217;ve done some reading about presenting somewhat formal proofs (a bit shy of those that can be machine checked), and wanted LaTeX packages that could help me with it.  In particular, tedious programming language proofs by near-trivial induction over syntactic structures.  I didn&#8217;t find anything great, but I did find some packages.


Some stuff [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve done some reading about presenting somewhat formal proofs (a bit shy of those that can be machine checked), and wanted LaTeX packages that could help me with it.  In particular, tedious programming language proofs by near-trivial induction over syntactic structures.  I didn&#8217;t find anything great, but I did find some packages.
<span id="more-12"></span></p>

<p>Some stuff that Leslie Lamport wrote would be nice if it didn&#8217;t conflict with every other style file; I edited it to remove the conflicts and I&#8217;m using it now.</p>

<p><a href="http://research.microsoft.com/users/lamport/latex/latex.html">http://research.microsoft.com/users/lamport/latex/latex.html
</a>
Also, since we are regularly pushing proofs to appendices:</p>

<p><a href="http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=thrmappendix">http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=thrmappendix</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2007/02/05/presenting-semi-formal-proofs-in-latex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
