diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 3.3.0.1
+
+  * Equality on optional values no longer crashes
+
 # 3.3.0.0
 
   * Allow decimal specifiers in format strings
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -52,12 +52,12 @@
 
 # Documentation
 
-See the [guide](https://vmchale.github.io/jacinda/) (archived on [Hackage](https://hackage.haskell.org/package/jacinda/src/doc/guide.pdf), which contains a tutorial
+See the [guide](https://vmchale.github.io/jacinda/) (archived on [Hackage](https://hackage.haskell.org/package/jacinda/src/doc/guide.pdf)), which contains a tutorial
 on some of the features as well as examples.
 
 The [manpages](https://hackage.haskell.org/package/jacinda/src/man/ja.1) document the builtins and provide a syntax reference.
 
-See the [rosetta](./ROSETTA.md) showing AWK alongside, or the [examples][./EXAMPLES.md] for its own capabilities.
+See the [rosetta](./ROSETTA.md) showing AWK alongside, or the [examples](./EXAMPLES.md) for its own capabilities.
 
 # Status
 
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -9,7 +9,7 @@
 import           File
 import           System.IO       (IOMode (WriteMode), withFile)
 
-hrun ifp e m fp = withFile "/dev/null" WriteMode $ \h -> runOnFile [] "(bench)" e [] m fp h
+hrun ifp e m fp = withFile "/dev/null" WriteMode $ \h -> runOnFile [] Nothing e [] m fp h
 runs e m fp = nfIO $ hrun "(bench)" e m fp
 fruns ifp m fp = nfIO $ do { contents <- TIO.readFile ifp; hrun ifp contents m fp }
 
diff --git a/doc/guide.pdf b/doc/guide.pdf
Binary files a/doc/guide.pdf and b/doc/guide.pdf differ
diff --git a/examples/cargoLockVersion.jac b/examples/cargoLockVersion.jac
new file mode 100644
--- /dev/null
+++ b/examples/cargoLockVersion.jac
@@ -0,0 +1,7 @@
+:set rs := /\[\[package\]\]/;
+:set fs :=/\n+/;
+
+fn any(p,xs) :=
+  (||)|>p"xs;
+
+{any (~/name = "libc"/) `$}{(~/version = "/) #. `$}
diff --git a/examples/path.jac b/examples/path.jac
--- a/examples/path.jac
+++ b/examples/path.jac
@@ -1,4 +1,5 @@
 {. echo $PATH | ja run examples/path.jac
+{. ja run examples/path.jac <(echo $PATH)
 fn path(x) :=
   ([x+'\n'+y]) |> (splitc x ':');
 
diff --git a/examples/pubmed2tex.jac b/examples/pubmed2tex.jac
new file mode 100644
--- /dev/null
+++ b/examples/pubmed2tex.jac
@@ -0,0 +1,40 @@
+{. ja run pubmed2tex.jac -i citation.nbib
+:set rs:=/\r\n/;
+
+{. 10.1016/j.tig.2011.10.004 [doi]
+fn doi(record) :=
+  record ~* 1 /([^ ]*) \[doi/;
+
+fn year(dd) :=
+  dd ~* 1 /(\d{4})/;
+
+fn pfield(label,r) :=
+  '    ' + label + '={' + r + '},';
+
+fn collateAu(r) :=
+  r ~* 1 /^FAU - (.*)$/;
+
+fn bind(f,x) :=
+  option None f x;
+
+fn texpaginate() := sub1 /-/ '--';
+
+fn field(r) :=
+  let 
+    val key := r ~* 1 /^([A-Z ]{4})-/
+    val value := r ~* 2 /^([A-Z ]{4})-\s*(.*)/
+  in
+     ?key=Some 'TI  ';(pfield 'title')¨value
+    ;?key=Some 'AID ';(pfield 'doi')¨bind doi value
+    ;?key=Some 'DP  ';(pfield 'year')¨bind year value
+    ;?key=Some 'JT  ';(pfield 'journal')¨value
+    ;?key=Some 'VI  ';(pfield 'volume')¨value
+    ;?key=Some 'IP  ';(pfield 'number')¨value
+    ;?key=Some 'PG  ';(λr. pfield 'pages' (texpaginate r))¨value
+    ;None
+  end;
+
+let
+  val au := ',\n    author={'+([x+' and '+y]|>(collateAu:?$0))+'},\n'
+  val rec := [x+'\n'+y]|>(field:?$0)
+in '@article{pubmed'+au+rec+'\n}' end
diff --git a/jacinda.cabal b/jacinda.cabal
--- a/jacinda.cabal
+++ b/jacinda.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               jacinda
-version:            3.3.0.0
+version:            3.3.0.1
 license:            AGPL-3.0-only
 license-file:       COPYING
 maintainer:         vamchale@gmail.com
@@ -29,7 +29,10 @@
     examples/*.jac
     examples/otool/*.jac
     test/golden/*.out
+    test/golden/*.bib
+    test/data/*.nbib
     test/data/a.csv
+    test/data/Cargo.lock
     test/data/cabal-info
     test/data/cabal-plan
     test/data/cdeps
@@ -64,7 +67,7 @@
         -Wincomplete-uni-patterns -Wincomplete-record-updates
         -Wredundant-constraints -Widentities -Wcpp-undef
         -Wmissing-export-lists -Wunused-packages -Wno-x-partial
-        -Wno-missing-signatures
+        -Wno-missing-signatures -Wredundant-bang-patterns
 
 library jacinda-lib
     import:           warnings
diff --git a/src/File.hs b/src/File.hs
--- a/src/File.hs
+++ b/src/File.hs
@@ -10,7 +10,7 @@
 import           Control.Exception                (Exception, throw, throwIO)
 import           Control.Monad.IO.Class           (liftIO)
 import           Control.Monad.Trans.State.Strict (StateT, get, put, runState, runStateT)
-import           Data.Bifunctor                   (second)
+import           Data.Bifunctor                   (first, second)
 import qualified Data.ByteString                  as BS
 import qualified Data.ByteString.Lazy             as BSL
 import qualified Data.ByteString.Lazy.Char8       as ASCIIL
@@ -58,18 +58,18 @@
         Right (st', ([], ds)) -> put st' $> (rwD <$> ds)
         Right (st', (is, ds)) -> do {put st'; dss <- traverse (parseLib incls) is; pure (concat dss ++ fmap rwD ds)}
 
-parseP :: [FilePath] -> FilePath -> T.Text -> [(T.Text, Value)] -> StateT AlexUserState IO (Program AlexPosn)
+parseP :: [FilePath] -> Maybe FilePath -> T.Text -> [(T.Text, Value)] -> StateT AlexUserState IO (Program AlexPosn)
 parseP incls fn src var = do
     st <- get
     case parseWithCtx src var st of
-        Left err -> liftIO $ throwIO (FPos fn<$>err)
+        Left err -> liftIO $ throwIO (srcErr fn err)
         Right (st', (is, Program ds e)) -> do
             put st'
             dss <- traverse (parseLib incls) is
             pure $ Program (concat dss ++ fmap rwD ds) (rwE e)
 
 -- | Parse + rename
-parsePWithMax :: [FilePath] -> FilePath -> T.Text -> [(T.Text, T.Text)] -> IO (Program AlexPosn, Int)
+parsePWithMax :: [FilePath] -> Maybe FilePath -> T.Text -> [(T.Text, T.Text)] -> IO (Program AlexPosn, Int)
 parsePWithMax incls fn src vars = uncurry rP.swap.second fst3 <$> runStateT (parseP incls fn src vars) alexInitUserState
     where fst3 (x,_,_) = x
 
@@ -79,8 +79,9 @@
 type FileBS = BS.ByteString
 
 data FPos = FPos { filen :: String, pos :: !AlexPosn }
+          | CLI { pos :: !AlexPosn }
 
-instance Pretty FPos where pretty (FPos f l) = pretty f <> ":" <> pretty l
+instance Pretty FPos where pretty (FPos f l) = pretty f <> ":" <> pretty l; pretty (CLI l) = pretty l
 
 tcompile=compileDefault.encodeUtf8
 
@@ -141,7 +142,7 @@
 
 runOnBytes :: [FilePath]
            -> FilePath -- ^ Data file name, for @nf@
-           -> FilePath -- ^ For error locations
+           -> Maybe FilePath -- ^ For error locations
            -> T.Text -- ^ Program
            -> [(T.Text, Value)]
            -> Mode
@@ -151,7 +152,7 @@
 runOnBytes incls fp fn src vars mode contents h = do
     incls' <- defaultIncludes <*> pure incls
     (ast, m) <- parsePWithMax incls' fn src vars
-    (typed, i) <- yIO fn $ runTyM m (tyP ast)
+    (typed, i) <- yIO $ first (srcErr fn) $ runTyM m (tyP ast)
     let (eI, j) = ib i typed
     m'Throw $ cF eI
     let (e', k) = runState (eta eI) j
@@ -169,7 +170,7 @@
         (_, CSV) -> let ctxs = csvCtx contents in cont ctxs
 
 runStdin :: [FilePath]
-         -> FilePath -- ^ For error location
+         -> Maybe FilePath -- ^ For error location
          -> T.Text -- ^ Program
          -> [(T.Text, Value)]
          -> Mode
@@ -177,7 +178,7 @@
 runStdin is src fn vars m = do {b <- BSL.hGetContents stdin; runOnBytes is "(stdin)" src fn vars m b stdout}
 
 runOnFile :: [FilePath]
-          -> FilePath
+          -> Maybe FilePath
           -> T.Text
           -> [(T.Text, Value)]
           -> Mode
@@ -189,15 +190,16 @@
 tcIO :: [FilePath] -> FilePath -> T.Text -> IO ()
 tcIO incls fn src = do
     incls' <- defaultIncludes <*> pure incls
-    (ast, m) <- parsePWithMax incls' fn src []
-    (pT, i) <- yIO fn $ runTyM m (tyP ast)
+    (ast, m) <- parsePWithMax incls' (Just fn) src []
+    (pT, i) <- yIO $ first (FPos fn<$>) $ runTyM m (tyP ast)
     let (eI, _) = ib i pT
     m'Throw $ cF eI
 
 m'Throw :: Exception e => Maybe e -> IO ()
 m'Throw = traverse_ throwIO
 
-yIO fp = either (throwIO.(FPos fp<$>)) pure
+yIO = either throwIO pure
+srcErr fp = fmap (maybe CLI FPos fp)
 
 yeet :: Exception e => Either e a -> a
 yeet = either throw id
diff --git a/src/Jacinda/Backend/T.hs b/src/Jacinda/Backend/T.hs
--- a/src/Jacinda/Backend/T.hs
+++ b/src/Jacinda/Backend/T.hs
@@ -401,6 +401,12 @@
 (EApp _ (EApp _ (BB (TyArr (TyB TyStr) _) op) x0) x1) @> b | Just rel <- binRel op = do
     x0e <- asS<$>(x0@>b); x1e <- asS<$>(x1@>b)
     pure (mkB (rel x0e x1e))
+(EApp _ (EApp _ (BB (TyArr (TyB TyOption:$t@(TyB TyStr)) _) Eq) x0) x1) @> b = do
+    x0e <- asM<$>(x0@>b); x1e <- asM<$>(x1@>b)
+    case (x0e,x1e) of
+        (Nothing, Nothing)   -> pure (mkB True)
+        (Just e0b, Just e1b) -> (EApp tyB (EApp (t~>tyB) (BB (TyArr t (t~>t~>tyB)) Eq) e0b) e1b) @> b
+        _                    -> pure (mkB False)
 (EApp _ (EApp _ (BB (TyArr (TyB TyStr) _) Plus) x0) x1) @> b = do
     x0e <- x0@>b; x1e <- x1@>b
     pure (mkStr (asS x0e<>asS x1e))
diff --git a/src/Jacinda/Check/Field.hs b/src/Jacinda/Check/Field.hs
--- a/src/Jacinda/Check/Field.hs
+++ b/src/Jacinda/Check/Field.hs
@@ -26,9 +26,9 @@
 cF Guarded{} = Nothing; cF Implicit{} = Nothing
 cF Lit{} = Nothing; cF RegexLit{} = Nothing;
 cF NB{} = Nothing; cF UB{} = Nothing; cF BB{} = Nothing; cF TB{} = Nothing
-cF Var{} = Nothing; cF (Tup _ es) = foldMapAlternative cF es; cF (Anchor _ es) = foldMapAlternative cF es
-cF (Arr _ es) = foldMapAlternative cF es; cF (Rec _ es) = foldMapAlternative (cF.snd) es; cF (EApp _ e e') = cF e <|> cF e'
-cF (Cond _ p e e') = cF p <|> cF e <|> cF e'; cF (OptionVal _ e) = foldMapAlternative cF e
+cF Var{} = Nothing; cF (Tup _ es) = cF||>es; cF (Anchor _ es) = cF||>es
+cF (Arr _ es) = cF||>es; cF (Rec _ es) = (cF.snd) ||> es; cF (EApp _ e e') = cF e <|> cF e'
+cF (Cond _ p e e') = cF p <|> cF e <|> cF e'; cF (OptionVal _ e) = cF||>e
 cF (Lam _ _ e) = cF e; cF Let{} = error "Inlining unexpectedly failed?"
 cF RC{} = error "Sanity check failed. Regex should not be compiled at this time."
 cF Dfn{} = desugar; cF Paren{} = desugar; cF ResVar{} = desugar
@@ -37,7 +37,7 @@
 isS :: T -> Bool
 isS (TyB TyStream:$_) = True; isS _ = False
 
-foldMapAlternative :: (Traversable t, Alternative f) => (a -> f b) -> t a -> f b
-foldMapAlternative f xs = asum (f <$> xs)
+(||>) :: (Traversable t, Alternative f) => (a -> f b) -> t a -> f b
+f ||> xs = asum (f <$> xs)
 
 desugar = error "Internal error. Should have been desugared by now."
diff --git a/src/R.hs b/src/R.hs
--- a/src/R.hs
+++ b/src/R.hs
@@ -84,8 +84,8 @@
 hasY :: E a -> Bool
 hasY = g where
     g (ResVar _ Y)           = True
-    g (Tup _ es)             = any g es
-    g (Rec _ es)             = any (g.snd) es
+    g (Tup _ es)             = g!|es
+    g (Rec _ es)             = (g.snd)!|es
     g (OptionVal _ (Just e)) = g e
     g (EApp _ e0 e1)         = g e0 || g e1
     g Dfn{}                  = error "nested dfns not yet implemented"
@@ -94,10 +94,15 @@
     g (Paren _ e)            = g e
     g (Guarded _ p e)        = g p || g e
     g (Implicit _ e)         = g e
-    g (Arr _ es)             = any g es
-    g (Anchor _ es)          = any g es
+    g (Arr _ es)             = g!|es
+    g (Anchor _ es)          = g!|es
     g (Cond _ p e0 e1)       = g e0 || g e1 || g p
     g _                      = False
+
+    infixr 6 !|
+
+    (!|) :: Foldable t => (a -> Bool) -> t a -> Bool
+    (!|) = any
 
 replaceXY :: (a -> Nm a) -- ^ @x@
           -> (a -> Nm a) -- ^ @y@
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -16,7 +16,7 @@
 import           Test.Tasty.Golden    (goldenVsString)
 import           Test.Tasty.HUnit
 
-eio :: FilePath -- ^ Source filename
+eio :: Maybe FilePath -- ^ Source filename
     -> T.Text
     -> Mode
     -> FilePath -- ^ Input
@@ -32,7 +32,7 @@
    -> BSL.ByteString -- ^ Expected output
    -> TestTree
 ep e m fp expected = testCase (T.unpack e) $ do
-    actual <- eio undefined e m fp
+    actual <- eio Nothing e m fp
     actual @?= expected <> "\n"
 
 harnessF e m fp o = goldenVsString (T.unpack e) o $ eio undefined e m fp
@@ -43,7 +43,7 @@
         -> FilePath -- ^ Expected output
         -> TestTree
 harness src m fp o =
-    goldenVsString src o $ do {t <- TIO.readFile src; eio src t m fp}
+    goldenVsString src o $ do {t <- TIO.readFile src; eio (Just src) t m fp}
 
 main :: IO ()
 main = defaultMain $
@@ -51,7 +51,10 @@
         testGroup "stream"
           [ harness "examples/otool/rpath.jac" awk "test/data/otool" "test/golden/rpath.out"
           , harness "examples/otool/dllibs.jac" awk "test/data/otool" "test/golden/ldlib.out"
+          , harness "examples/pubmed2tex.jac" awk "test/data/3221331.nbib" "test/golden/holland1988.bib"
+          , harness "examples/pubmed2tex.jac" awk "test/data/22078126.nbib" "test/golden/gonadalsex.bib"
           , harness "test/examples/ghc-filt.jac" awk "test/data/ghc" "test/golden/ghc.out"
+          , harness "examples/cargoLockVersion.jac" awk "test/data/Cargo.lock" "test/golden/cargo.out"
           , ep "[x ~* 1 /(\\d+(\\.\\d+)*)/]:?{%/Versions available:/}{[y]|>`$}"
                 (AWK (Just "\\s*,\\s*") (Just "\\n[^:\\n]*:") True)
                 "test/data/cabal-info"
diff --git a/test/data/22078126.nbib b/test/data/22078126.nbib
new file mode 100644
--- /dev/null
+++ b/test/data/22078126.nbib
@@ -0,0 +1,77 @@
+PMID- 22078126
+OWN - NLM
+STAT- MEDLINE
+DCOM- 20120427
+LR  - 20240610
+IS  - 0168-9525 (Print)
+IS  - 0168-9525 (Electronic)
+IS  - 0168-9525 (Linking)
+VI  - 28
+IP  - 2
+DP  - 2012 Feb
+TI  - The end of gonad-centric sex determination in mammals.
+PG  - 55-61
+LID - 10.1016/j.tig.2011.10.004 [doi]
+AB  - The 20th-century theory of mammalian sex determination states that the embryo is 
+      sexually indifferent until the differentiation of gonads, after which sex 
+      differences in phenotype are caused by the differential effects of gonadal 
+      hormones. However, this theory is inadequate because some sex differences precede 
+      differentiation of the gonads and/or are determined by non-gonadal effects of the 
+      sexual inequality in the number and type of sex chromosomes. In this article, I 
+      propose a general theory of sex determination, which recognizes multiple parallel 
+      primary sex-determining pathways initiated by genes or factors encoded by the sex 
+      chromosomes. The separate sex-specific pathways interact to synergize with or 
+      antagonize each other, enhancing or reducing sex differences in phenotype.
+CI  - Copyright © 2011 Elsevier Ltd. All rights reserved.
+FAU - Arnold, Arthur P
+AU  - Arnold AP
+AD  - Department of Integrative Biology & Physiology, Laboratory of Neuroendocrinology 
+      of the Brain Research Institute, University of California, Los Angeles, CA 
+      90095-7239, USA. arnold@ucla.edu
+LA  - eng
+GR  - R01 NS043196/NS/NINDS NIH HHS/United States
+GR  - MH059268/MH/NIMH NIH HHS/United States
+GR  - DC000217/DC/NIDCD NIH HHS/United States
+GR  - R01 DC000217/DC/NIDCD NIH HHS/United States
+GR  - R01 DK083561-03/DK/NIDDK NIH HHS/United States
+GR  - R01 MH059268-03/MH/NIMH NIH HHS/United States
+GR  - R01 GM059268/GM/NIGMS NIH HHS/United States
+GR  - DK08356/DK/NIDDK NIH HHS/United States
+GR  - NS043196/NS/NINDS NIH HHS/United States
+GR  - R01 DK083561/DK/NIDDK NIH HHS/United States
+GR  - R01 NS043196-08/NS/NINDS NIH HHS/United States
+GR  - R01 DC000217-24/DC/NIDCD NIH HHS/United States
+PT  - Journal Article
+PT  - Research Support, N.I.H., Extramural
+DEP - 20111109
+PL  - England
+TA  - Trends Genet
+JT  - Trends in genetics : TIG
+JID - 8507085
+SB  - IM
+MH  - Animals
+MH  - Gene Expression Regulation, Developmental
+MH  - Genome
+MH  - Gonads/embryology/*growth & development/metabolism
+MH  - Humans
+MH  - Mammals/embryology/*genetics/growth & development
+MH  - *Sex Determination Processes
+MH  - Sex Differentiation
+PMC - PMC3268825
+MID - NIHMS333647
+EDAT- 2011/11/15 06:00
+MHDA- 2012/04/28 06:00
+PMCR- 2013/02/01
+CRDT- 2011/11/15 06:00
+PHST- 2011/08/31 00:00 [received]
+PHST- 2011/10/16 00:00 [revised]
+PHST- 2011/10/17 00:00 [accepted]
+PHST- 2011/11/15 06:00 [entrez]
+PHST- 2011/11/15 06:00 [pubmed]
+PHST- 2012/04/28 06:00 [medline]
+PHST- 2013/02/01 00:00 [pmc-release]
+AID - S0168-9525(11)00170-3 [pii]
+AID - 10.1016/j.tig.2011.10.004 [doi]
+PST - ppublish
+SO  - Trends Genet. 2012 Feb;28(2):55-61. doi: 10.1016/j.tig.2011.10.004. Epub 2011 Nov 
+      9.
diff --git a/test/data/3221331.nbib b/test/data/3221331.nbib
new file mode 100644
--- /dev/null
+++ b/test/data/3221331.nbib
@@ -0,0 +1,61 @@
+PMID- 3221331
+OWN - NLM
+STAT- MEDLINE
+DCOM- 19890316
+LR  - 20190828
+IS  - 0022-3999 (Print)
+IS  - 0022-3999 (Linking)
+VI  - 32
+IP  - 6
+DP  - 1988
+TI  - Anorexia nervosa: evidence for a genetic basis.
+PG  - 561-71
+AB  - This paper reports the preliminary results of a combined twin and family study of 
+      anorexia nervosa. Fifty-six per cent of the 25 female monozygotic (MZ) twin pairs 
+      and 5% of the 20 female dizygotic (DZ) twin pairs were concordant for anorexia 
+      nervosa. Nearly 5% of other female first degree relatives also had a history of 
+      anorexia nervosa. Analysis of data from the Eating Disorders Questionnaire (EDI) 
+      given to the twins and data as to weight loss, length of amenorrhoea and other 
+      characteristics of anorexia nervosa, together with the twin and family data, 
+      supports the hypothesis that genetic factors are very significant in the 
+      aetiology of anorexia nervosa. Analysis of this data using established techniques 
+      of psychiatric genetics suggested that up to 80% of the variance in liability to 
+      anorexia nervosa may be accounted for by genetic factors. The problems of this 
+      type of analysis are discussed as is the background to the genetics of weight and 
+      appetite control. A genetic/environmental model accounting for the features of 
+      anorexia nervosa is proposed.
+FAU - Holland, A J
+AU  - Holland AJ
+AD  - Department of Psychiatry, Institute of Psychiatry, London, U.K.
+FAU - Sicotte, N
+AU  - Sicotte N
+FAU - Treasure, J
+AU  - Treasure J
+LA  - eng
+PT  - Journal Article
+PT  - Research Support, Non-U.S. Gov't
+PL  - England
+TA  - J Psychosom Res
+JT  - Journal of psychosomatic research
+JID - 0376333
+SB  - IM
+MH  - Adult
+MH  - Amenorrhea/etiology
+MH  - Anorexia Nervosa/*genetics
+MH  - Body Image
+MH  - Body Weight
+MH  - *Diseases in Twins
+MH  - Female
+MH  - Humans
+MH  - Models, Genetic
+MH  - Twins, Dizygotic
+MH  - Twins, Monozygotic
+EDAT- 1988/01/01 00:00
+MHDA- 1988/01/01 00:01
+CRDT- 1988/01/01 00:00
+PHST- 1988/01/01 00:00 [pubmed]
+PHST- 1988/01/01 00:01 [medline]
+PHST- 1988/01/01 00:00 [entrez]
+AID - 10.1016/0022-3999(88)90004-9 [doi]
+PST - ppublish
+SO  - J Psychosom Res. 1988;32(6):561-71. doi: 10.1016/0022-3999(88)90004-9.
diff --git a/test/data/Cargo.lock b/test/data/Cargo.lock
new file mode 100644
--- /dev/null
+++ b/test/data/Cargo.lock
@@ -0,0 +1,530 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "log",
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
+
+[[package]]
+name = "arbitrary"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
+dependencies = [
+ "derive_arbitrary",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bstr"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "derive_arbitrary"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "env_logger"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "termcolor",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "indexmap"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "lexopt"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"
+
+[[package]]
+name = "libc"
+version = "0.2.167"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+dependencies = [
+ "log",
+]
+
+[[package]]
+name = "memmap2"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quickcheck"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+dependencies = [
+ "aho-corasick",
+ "anyhow",
+ "doc-comment",
+ "env_logger",
+ "memchr",
+ "once_cell",
+ "quickcheck",
+ "regex-automata",
+ "regex-syntax",
+ "regex-test",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.8"
+dependencies = [
+ "aho-corasick",
+ "anyhow",
+ "bstr",
+ "doc-comment",
+ "env_logger",
+ "log",
+ "memchr",
+ "quickcheck",
+ "regex-syntax",
+ "regex-test",
+]
+
+[[package]]
+name = "regex-cli"
+version = "0.2.1"
+dependencies = [
+ "anyhow",
+ "bstr",
+ "lexopt",
+ "log",
+ "memmap2",
+ "regex",
+ "regex-automata",
+ "regex-lite",
+ "regex-syntax",
+ "tabwriter",
+ "textwrap",
+]
+
+[[package]]
+name = "regex-lite"
+version = "0.1.6"
+dependencies = [
+ "anyhow",
+ "regex-test",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+dependencies = [
+ "arbitrary",
+]
+
+[[package]]
+name = "regex-test"
+version = "0.1.1"
+dependencies = [
+ "anyhow",
+ "bstr",
+ "serde",
+ "toml",
+]
+
+[[package]]
+name = "rure"
+version = "0.2.2"
+dependencies = [
+ "libc",
+ "regex",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.215"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.215"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tabwriter"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a327282c4f64f6dc37e3bba4c2b6842cc3a992f204fa58d917696a89f691e5f6"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
+
+[[package]]
+name = "toml"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "winnow"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
+dependencies = [
+ "memchr",
+]
diff --git a/test/golden/cargo.out b/test/golden/cargo.out
new file mode 100644
--- /dev/null
+++ b/test/golden/cargo.out
@@ -0,0 +1,1 @@
+⟨version = "0.2.167"⟩
diff --git a/test/golden/gonadalsex.bib b/test/golden/gonadalsex.bib
new file mode 100644
--- /dev/null
+++ b/test/golden/gonadalsex.bib
@@ -0,0 +1,10 @@
+@article{pubmed,
+    author={Arnold, Arthur P},
+    volume={28},
+    number={2},
+    year={2012},
+    title={The end of gonad-centric sex determination in mammals.},
+    pages={55--61},
+    journal={Trends in genetics : TIG},
+    doi={10.1016/j.tig.2011.10.004},
+}
diff --git a/test/golden/holland1988.bib b/test/golden/holland1988.bib
new file mode 100644
--- /dev/null
+++ b/test/golden/holland1988.bib
@@ -0,0 +1,10 @@
+@article{pubmed,
+    author={Holland, A J and Sicotte, N and Treasure, J},
+    volume={32},
+    number={6},
+    year={1988},
+    title={Anorexia nervosa: evidence for a genetic basis.},
+    pages={561--71},
+    journal={Journal of psychosomatic research},
+    doi={10.1016/0022-3999(88)90004-9},
+}
diff --git a/x/Opt.hs b/x/Opt.hs
--- a/x/Opt.hs
+++ b/x/Opt.hs
@@ -130,12 +130,12 @@
 
 run :: Cmd -> IO ()
 run (TC fp is)                         = tcIO is fp =<< TIO.readFile fp
-run (Run fp fs rs Nothing is vs h)    = do { contents <- TIO.readFile fp ; runStdin is fp contents vs (AWK fs rs h) }
-run (Run fp fs rs (Just dat) is vs h) = do { contents <- TIO.readFile fp ; runOnFile is fp contents vs (AWK fs rs h) dat stdout }
+run (Run fp fs rs Nothing is vs h)    = do { contents <- TIO.readFile fp ; runStdin is (Just fp) contents vs (AWK fs rs h) }
+run (Run fp fs rs (Just dat) is vs h) = do { contents <- TIO.readFile fp ; runOnFile is (Just fp) contents vs (AWK fs rs h) dat stdout }
 run (Expr eb f fs a u c rs is h)      =
     case f of
-        Nothing -> runStdin is "(no file info)" eb [] (m h)
-        Just fp -> runOnFile is "(no file info)" eb [] (m h) fp stdout
+        Nothing -> runStdin is Nothing eb [] (m h)
+        Just fp -> runOnFile is Nothing eb [] (m h) fp stdout
   where
     m = ap a u c fs rs
 run (Eval e)                          = print (exprEval e)
