From 738806112bc0ee1711c6f170361d382c7d4265e8 Mon Sep 17 00:00:00 2001
From: John MacFarlane <jgm@berkeley.edu>
Date: Sun, 23 Oct 2016 22:16:00 +0200
Subject: [PATCH] Allow binary formats to be written to stdout unless tty
 output.

Only works on posix.  On Windows, pandoc works as before and
requires an output file parameter for binary formats.

Closes #2677.
---
 pandoc.cabal |  3 +++
 pandoc.hs    | 20 +++++++++++++++-----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/pandoc.cabal b/pandoc.cabal
index 57a8f6020..da9d005ef 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -442,6 +442,9 @@ Executable pandoc
   Ghc-Prof-Options: -fprof-auto-exported -rtsopts -with-rtsopts=-K16m
   if os(windows)
     Cpp-options:      -D_WINDOWS
+  else
+    Build-Depends:  unix >= 2.4 && < 2.8
+
   Default-Language: Haskell98
   Other-Extensions: PatternGuards, OverloadedStrings,
                     ScopedTypeVariables, GeneralizedNewtypeDeriving,
diff --git a/pandoc.hs b/pandoc.hs
index 4f87947e7..541d17ef3 100644
--- a/pandoc.hs
+++ b/pandoc.hs
@@ -74,6 +74,10 @@ import Text.Pandoc.Readers.Txt2Tags (getT2TMeta)
 import Paths_pandoc (getDataDir)
 import Text.Printf (printf)
 import Text.Pandoc.Error
+#ifndef _WINDOWS
+import System.Posix.Terminal (queryTerminal)
+import System.Posix.IO (stdOutput)
+#endif
 
 type Transform = Pandoc -> Pandoc
 
@@ -1357,7 +1361,12 @@ convertWithOpts opts args = do
                       , readerFileScope   = fileScope
                       }
 
-  when (not (isTextFormat format) && outputFile == "-") $
+#ifdef _WINDOWS
+  let istty = True
+#else
+  istty <- queryTerminal stdOutput
+#endif
+  when (istty && not (isTextFormat format) && outputFile == "-") $
     err 5 $ "Cannot write " ++ format ++ " output to stdout.\n" ++
             "Specify an output file using the -o option."
 
@@ -1457,8 +1466,9 @@ convertWithOpts opts args = do
            applyTransforms transforms >=>
            applyFilters datadir filters' [format]) doc
 
-  let writeBinary :: B.ByteString -> IO ()
-      writeBinary = B.writeFile (UTF8.encodePath outputFile)
+  let writeFnBinary :: FilePath -> B.ByteString -> IO ()
+      writeFnBinary "-" = B.putStr
+      writeFnBinary f   = B.writeFile (UTF8.encodePath f)
 
   let writerFn :: FilePath -> String -> IO ()
       writerFn "-" = UTF8.putStr
@@ -1466,7 +1476,7 @@ convertWithOpts opts args = do
 
   case writer of
     IOStringWriter f -> f writerOptions doc' >>= writerFn outputFile
-    IOByteStringWriter f -> f writerOptions doc' >>= writeBinary
+    IOByteStringWriter f -> f writerOptions doc' >>= writeFnBinary outputFile
     PureStringWriter f
       | pdfOutput -> do
               -- make sure writer is latex or beamer or context or html5
@@ -1486,7 +1496,7 @@ convertWithOpts opts args = do
 
               res <- makePDF pdfprog f writerOptions doc'
               case res of
-                   Right pdf -> writeBinary pdf
+                   Right pdf -> writeFnBinary outputFile pdf
                    Left err' -> do
                      B.hPutStr stderr err'
                      B.hPut stderr $ B.pack [10]