-- | Platform dependent previewing of PDF files. On Windows, we try to -- run Acrobat Reader. On Mac, we try to run Preview. On Linux, we try -- to run Acrobat Reader or Xpdf. If this fails, we abort the program -- with a platform dependent error message. module Quipper.Utils.Preview where import Control.Exception import System.Environment import System.Exit import System.Info import System.IO import System.IO.Error import System.Process -- | Sequentially try one or more IO computations, until one of them -- completes without an IO error. If all of them fail, re-throw the -- error from the last one. try_several_IO :: [IO a] -> IO a try_several_IO [] = error "try_several_IO" try_several_IO [h] = do catchIOError h (\e -> throw e) try_several_IO (h:t) = do catchIOError h (\e -> try_several_IO t) -- | @'system_pdf_viewer' zoom pdffile@: Call a system-specific PDF -- viewer on /pdffile/ file. The /zoom/ argument is out of 100 and may -- or may not be ignored by the viewer. system_pdf_viewer :: Double -> String -> IO () system_pdf_viewer zoom pdffile = do envList <- getEnvironment if (elem ("OS", "Windows_NT") envList) then windows_pdf_viewer zoom pdffile else if (os == "darwin") then macos_pdf_viewer zoom pdffile else linux_pdf_viewer zoom pdffile -- | Like 'system_pdf_viewer', but specialized to Windows. windows_pdf_viewer :: Double -> String -> IO () windows_pdf_viewer zoom pdffile = catchIOError body handler where body = do r <- system ("start /WAIT AcroRd32 " ++ pdffile) case r of ExitSuccess -> return () ExitFailure n -> acrord32_error n handler e = do name <- getProgName hPutStrLn stderr $ name ++ ": unable to preview PDF file. Please ensure that Acrobat Reader is installed." exitFailure acrord32_error n = do name <- getProgName hPutStrLn stderr $ name ++ ": unable to preview PDF file. Please ensure that Acrobat Reader is installed." exitFailure -- | Like 'system_pdf_viewer', but specialized to Mac OS. macos_pdf_viewer :: Double -> String -> IO () macos_pdf_viewer zoom pdffile = catchIOError body handler where body = do rawSystem "open" [pdffile] rawSystem "sleep" ["1"] -- required or the file may be deleted too soon return () handler e = do name <- getProgName hPutStrLn stderr $ name ++ ": unable to preview PDF file. There seems to be a problem with Preview." exitFailure -- | Like 'system_pdf_viewer', but specialized to Linux. linux_pdf_viewer :: Double -> String -> IO () linux_pdf_viewer zoom pdffile = catchIOError body handler where body = do try_several_IO [ rawSystem "acroread" ["/a", "zoom=" ++ show zoom, pdffile], rawSystem "xpdf" ["-z", show zoom, pdffile] ] return () handler e = do name <- getProgName hPutStrLn stderr $ name ++ ": unable to preview PDF file. Please ensure that either Acrobat Reader or Xpdf are installed." exitFailure