diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 3.1.1.1
+
+  * Pretty-print `:set csv`
+  * `:set csv` inline case
+  * Fix bug in `mapMaybe` &c. synonym parsing
+
 # 3.1.1.0
 
   * Add `reintercalate` builtin
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -16,13 +16,15 @@
                       , bench "exprEval" $ nf exprEval "reintercalate ' ' (split '01-23-1987' /-/)"
                       ]
                 , bgroup "csv"
-                      [ bench "succdiff" $ nfIO (silence $ runOnFile [] "~.{ix>1}{`8}" CSV "bench/data/food-prices.csv") ]
+                      [ bench "dedup" $ nfIO (silence $ runOnFile [] "~.{ix>1}{`8}" CSV "bench/data/food-prices.csv")
+                      , bench "succdiff" $ nfIO (silence $ runOnFile [] "(%)\\. {%/Apple/}{`3:}" CSV "bench/data/food-prices.csv")
+                      ]
                 , bgroup "stream"
                       [ bench "path" $ nfIO (silence $ runOnFile [] "{|[x+'\\n'+y]|>`$}" (AWK (Just ":") Nothing) "bench/data/PATH")
                       , bench "RS" $ nfIO (silence $ runOnFile [] "$0" (AWK Nothing (Just ":")) "bench/data/PATH")
                       , bench "runOnFile" $ nfIO (silence $ runOnFile [] "(+)|0 {%/Bloom/}{1}" (AWK Nothing Nothing) "bench/data/ulysses.txt")
-                      , bench "runOnFile" $ nfIO (silence $ do { contents <- TIO.readFile "examples/wc.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/ulysses.txt" })
-                      , bench "runOnFile" $ nfIO (silence $ do { contents <- TIO.readFile "examples/span2.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/span.txt" })
+                      , bench "runOnFile/wc.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/wc.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/ulysses.txt" })
+                      , bench "runOnFile/span2.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/span2.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/span.txt" })
                       , bench "sedstream.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/sedstream.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/lines.txt" })
                       , bench "gnused.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/gnused.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/lines.txt" })
                       -- , bench "fungnused.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/fungnused.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/lines.txt" })
diff --git a/examples/slow.jac b/examples/slow.jac
deleted file mode 100644
--- a/examples/slow.jac
+++ /dev/null
@@ -1,1 +0,0 @@
-(+)|> ([x+'\n'+y]|>)¨{|captures `0 1 /-lHS([A-Aa-z][A-Za-z0-9\-]*\d+(\.\d+)*)/}
diff --git a/examples/tagsex.jac b/examples/tagsex.jac
new file mode 100644
--- /dev/null
+++ b/examples/tagsex.jac
@@ -0,0 +1,12 @@
+fn mkEx(s) :=
+  '/^' + s + '$/;';
+
+{. TODO: insert \zs at precise identifier! https://stackoverflow.com/a/31089753/11296354
+
+fn processStr(s) :=
+  let
+    val line := split s /[ \(:]+/
+    val outLine := sprintf '%s\t%s\t%s' (line.3 . fp . mkEx s)
+  in outLine end;
+
+processStr¨{%/fn +[[:lower:]][[:latin:]]*.*:=/}{`0}
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.1.1.0
+version:            3.1.1.1
 license:            AGPL-3.0-only
 license-file:       COPYING
 maintainer:         vamchale@gmail.com
diff --git a/man/ja.1 b/man/ja.1
--- a/man/ja.1
+++ b/man/ja.1
@@ -140,9 +140,6 @@
 \f[B]\[ti]?\f[R] Maybe match: return string if it is a match, otherwise None
 Str \-> Regex \-> Option Str
 .TP
-\f[B]\[at]\f[R] Intercalate
-List Str \-> Str \-> Str
-.TP
 \f[B]\[ti]*\f[R] Match, returning nth capture group
 Str \-> Int \-> Regex \-> Option Str
 .TP
diff --git a/src/A.hs b/src/A.hs
--- a/src/A.hs
+++ b/src/A.hs
@@ -372,6 +372,7 @@
     pretty FlushDecl        = ":flush;"
     pretty SetAsv           = ":set asv;"
     pretty SetUsv           = ":set usv;"
+    pretty SetCsv           = ":set csv;"
     pretty (SetOFS sep)     = ":set ofs :=" <+> "'" <> pretty sep <> "';"
     pretty (SetORS sep)     = ":set ors :=" <+> "'" <> pretty sep <> "';"
 
diff --git a/src/A/I.hs b/src/A/I.hs
--- a/src/A/I.hs
+++ b/src/A/I.hs
@@ -16,9 +16,7 @@
 import           Ty
 import           U
 
-data ISt a = ISt { renames :: !Renames
-                 , binds   :: IM.IntMap (E a)
-                 }
+data ISt a = ISt { renames :: !Renames, binds :: IM.IntMap (E a) }
 
 instance HasRenames (ISt a) where
     rename f s = fmap (\x -> s { renames = x }) (f (renames s))
@@ -41,7 +39,7 @@
 
 iD :: D T -> RM T ()
 iD (FunDecl n [] e) = do {eI <- iE e; modify (bind n eI)}
-iD SetFS{} = pure (); iD SetRS{} = pure (); iD SetAsv = pure (); iD SetUsv = pure ()
+iD SetFS{} = pure (); iD SetRS{} = pure (); iD SetAsv = pure (); iD SetUsv = pure (); iD SetCsv = pure ()
 iD SetORS{} = pure (); iD SetOFS{} = pure (); iD FlushDecl{} = pure ()
 iD FunDecl{} = desugar
 
diff --git a/src/File.hs b/src/File.hs
--- a/src/File.hs
+++ b/src/File.hs
@@ -98,6 +98,9 @@
     r (EApp l e0 e1)    = EApp l (r e0) (r e1)
     r e@Column{}        = e
     r e@IParseCol{}     = e
+    r e@IParseAllCol{}  = e
+    r e@FParseAllCol{}  = e
+    r e@ParseAllCol{}   = e
     r e@FParseCol{}     = e
     r e@ParseCol{}      = e
     r e@LastField{}     = e
diff --git a/src/Parser/Rw.hs b/src/Parser/Rw.hs
--- a/src/Parser/Rw.hs
+++ b/src/Parser/Rw.hs
@@ -54,12 +54,21 @@
 
 rwE :: E a -> E a
 rwE (EApp l0 (EApp l1 (EApp l2 ho@TB{} e3) e2) e1) =
-    (EApp l0 (EApp l1 (EApp l2 ho (rwE e3)) (rwE e2)) (rwE e1))
+    EApp l0 (EApp l1 (EApp l2 ho (rwE e3)) (rwE e2)) (rwE e1)
 rwE (EApp l0 (EApp l1 e0@(BB _ op0) e1) e2) | Just fi <- mFi op0 =
     case rwE e2 of
         (EApp l2 (EApp l3 e3@(BB _ op1) e4) e5) | Just fi' <- mFi op1, fi > fi' -> EApp l0 (EApp l1 e3 (rwE (EApp l2 (EApp l3 e0 e1) e4))) e5
         e2'                                                                     -> EApp l0 (EApp l1 e0 (rwE e1)) e2'
 rwE (EApp l op@(UB _ Dedup) e) = EApp l op (rwE e)
+rwE (EApp l (RwB l0 b) e') =
+    case rwE e' of
+        (EApp lϵ e1 e2) -> EApp l (EApp lϵ (BB l0 b) e1) e2
+        eϵ -> EApp l (BB l0 b) eϵ
+rwE (EApp l (RwT l0 t) e') =
+    case rwE e' of
+        (EApp lϵ (EApp lϵϵ e1 e2) e3) -> EApp l (EApp lϵ (EApp lϵϵ (TB l0 t) e1) e2) e3
+        (EApp lϵ e1 e2) -> EApp l (EApp lϵ (TB l0 t) e1) e2
+        eϵ -> EApp l (TB l0 t) eϵ
 rwE (EApp l e0 e') =
     case (e0, rwE e') of
         (_, EApp lϵ (EApp lϵϵ e3@(BB _ op) e4) e2) | Just{} <- mFi op -> EApp l (EApp lϵϵ e3 (rwE $ EApp lϵ e0 e4)) e2
@@ -95,3 +104,5 @@
 rwE e@ResVar{} = e
 rwE (Paren l e) = Paren l (rwE e)
 rwE (Cond l p e e') = Cond l (rwE p) (rwE e) (rwE e')
+rwE (RwB l b) = BB l b
+rwE (RwT l b) = TB l b
diff --git a/src/Ty.hs b/src/Ty.hs
--- a/src/Ty.hs
+++ b/src/Ty.hs
@@ -103,11 +103,13 @@
 maM (TyVar n) (TyVar n') | n == n' = Right mempty
 maM (TyVar (Nm _ (U i) _)) t = Right (IM.singleton i t)
 maM (TyArr t0 t1) (TyArr t0' t1') = (<>) <$> maM t0 t0' <*> maM t1' t1 -- TODO: I think <> is right
-maM (TyTup ts) (TyTup ts')        = fmap mconcat (zipWithM maM ts ts')
+maM (TyTup ts) (TyTup ts') = fmap mconcat (zipWithM maM ts ts')
 maM (Rho n _) (Rho n' _) | n == n' = Right mempty
-maM (Rho n rs) t@(Rho _ rs') | IM.keysSet rs' `IS.isSubsetOf` IM.keysSet rs = IM.insert (unU$unique n) t . mconcat <$> traverse (uncurry maM) (IM.elems (IM.intersectionWith (,) rs rs'))
-maM (Rho n rs) t@(TyTup ts) | length ts >= fst (IM.findMax rs) = IM.insert (unU$unique n) t . mconcat <$> traverse (uncurry maM) [ (ts!!(i-1),tϵ) | (i,tϵ) <- IM.toList rs ]
-maM t t'                              = Left $ MF t t'
+maM (Rho n rs) t@(Rho _ rs') | IM.keysSet rs' `IS.isSubsetOf` IM.keysSet rs
+    = IM.insert (unU$unique n) t . mconcat <$> traverse (uncurry maM) (IM.elems (IM.intersectionWith (,) rs rs'))
+maM (Rho n rs) t@(TyTup ts) | length ts >= fst (IM.findMax rs)
+    = IM.insert (unU$unique n) t . mconcat <$> traverse (uncurry maM) [ (ts!!(i-1),tϵ) | (i,tϵ) <- IM.toList rs ]
+maM t t' = Left $ MF t t'
 
 occ :: T -> IS.IntSet
 occ (TyVar (Nm _ (U i) _))  = IS.singleton i
@@ -127,7 +129,8 @@
 mgu l s (TyArr t0 t1) (TyArr t0' t1')  = do {s0 <- mguPrep l s t0 t0'; mguPrep l s0 t1 t1'}
 mgu l s (t0:$t1) (t0':$t1')            = do {s0 <- mguPrep l s t0 t0'; mguPrep l s0 t1 t1'}
 mgu l s (TyTup ts) (TyTup ts') | length ts == length ts' = zS (mguPrep l) s ts ts'
-mgu l s (Rho n rs) t'@(TyTup ts) | length ts >= fst (IM.findMax rs) && fst (IM.findMin rs) > 0 = tS_ (\sϵ (i, tϵ) -> IM.insert (unU$unique n) t' <$> mguPrep l sϵ (ts!!(i-1)) tϵ) s (IM.toList rs)
+mgu l s (Rho n rs) t'@(TyTup ts) | length ts >= fst (IM.findMax rs) && fst (IM.findMin rs) > 0
+    = tS_ (\sϵ (i, tϵ) -> IM.insert (unU$unique n) t' <$> mguPrep l sϵ (ts!!(i-1)) tϵ) s (IM.toList rs)
 mgu l s t@TyTup{} t'@Rho{} = mgu l s t' t
 mgu l s (Rho n rs) (Rho n' rs') = do
     rss <- tS_ (\sϵ (t0,t1) -> mguPrep l sϵ t0 t1) s $ IM.elems $ IM.intersectionWith (,) rs rs'
@@ -258,6 +261,7 @@
 tyDS s (SetRS bs)  = pure (SetRS bs, s)
 tyDS s (SetOFS bs) = pure (SetOFS bs, s)
 tyDS s (SetORS bs) = pure (SetORS bs, s)
+tyDS s SetCsv      = pure (SetCsv, s)
 tyDS s SetAsv      = pure (SetAsv, s)
 tyDS s SetUsv      = pure (SetUsv, s)
 tyDS s FlushDecl   = pure (FlushDecl, s)
@@ -286,7 +290,7 @@
 checkAmb e@(Arr ty _) | isAmbiguous ty = throwError $ Ambiguous ty (void e)
 checkAmb e@(Var ty _) | isAmbiguous ty = throwError $ Ambiguous ty (void e)
 checkAmb (Let _ bs e) = traverse_ checkAmb [e, snd bs]
-checkAmb (Lam _ _ e) = checkAmb e -- I think
+checkAmb (Lam _ _ e) = checkAmb e
 checkAmb e@(ParseAllCol t) | isAmbiguous t = throwError (Ambiguous t (void e))
 checkAmb e@(ParseCol t _) | isAmbiguous t = throwError (Ambiguous t (void e))
 checkAmb _ = pure ()
@@ -340,7 +344,7 @@
     pure $ a' ~> a' ~> a'
 
 desugar :: a
-desugar = error "Should have been de-sugared in an earlier stage!"
+desugar = error "Internal error: should have been de-sugared in an earlier stage!"
 
 tyE :: Ord a => E a -> TyM a (E T)
 tyE e = do
@@ -512,5 +516,5 @@
 tyES s (Anchor l es) = do
     (es', s') <- tS (\sϵ e -> do {(e',s0) <- tyES sϵ e; a <- freshTV "a"; s1 <- liftEither $ mguPrep l s0 (tyStream a) (eLoc e'); pure (e', s1)}) s es
     pure (Anchor (TyB TyUnit) es', s')
-tyES _ RC{} = error "Regex should not be compiled at this stage."
-tyES _ Dfn{} = desugar; tyES _ ResVar{} = desugar; tyES _ Paren{} = desugar
+tyES _ RC{} = error "Internal error: regex should not be compiled at this stage."
+tyES _ Dfn{} = desugar; tyES _ ResVar{} = desugar; tyES _ Paren{} = desugar; tyES _ RwB{} = desugar; tyES _ RwT{} = desugar
diff --git a/test/examples/bookend.jac b/test/examples/bookend.jac
deleted file mode 100644
--- a/test/examples/bookend.jac
+++ /dev/null
@@ -1,1 +0,0 @@
-/Disassembly of section \.text:/,,/Disassembly of section/$0
