packages feed

hurdle-0.3.0: src/Hurdle/Ar/TextDump.hs

{-# OPTIONS -Wall #-}

--------------------------------------------------------------------------------
-- |
-- Module      :  Hurdle.Ar.TextDump
-- Copyright   :  (c) Stephen Tetley 2009
-- License     :  BSD3
--
-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>
-- Stability   :  highly unstable
-- Portability :  
--
-- Pretty print as text...
--
--------------------------------------------------------------------------------

module Hurdle.Ar.TextDump where

import Hurdle.Base.Utils ( applyfs )
import Hurdle.Ar.Datatypes

import Data.Char
import Numeric
import Text.PrettyPrint.JoinPrint hiding ( length )



printArchive :: ArArchive -> IO ()
printArchive = putStr . archiveText

archiveText :: ArArchive -> String
archiveText = render . ppArchive

ppArchive :: ArArchive -> Doc
ppArchive a = 
        text              (ar_magic a)
    <%> (vcat $ map ppArchiveObject $ ar_objects a)



ppArchiveObject :: ArchiveObject -> Doc
ppArchiveObject = ppArHeader . ar_header

ppArHeader :: ArHeader -> Doc
ppArHeader a = 
    tableProlog "Header" (24,6) (applyfs fields a) 
  where
    ppf    = ppField 4 24   
    fields = 
       [ ppf 16 "name"                  (text . arh_name)
       , ppf 12 "date"                  (text . arh_date)
       , ppf 6  "user id"               (int  . arh_user_id)
       , ppf 6  "group id"              (int  . arh_group_id)
       , ppf 8  "mode"                  (text . arh_mode)
       , ppf 10 "size"                  (int . arh_size)
       , ppf 2  "trailer"               (tup2 . arh_trailer)
       ]
    tup2 (x:y:xs) = ppHex 2 (ord x) <+> ppHex 2 (ord y) <+> text xs
    tup2 xs       = text xs




--------------------------------------------------------------------------------
-- Helpers

tableProlog :: String -> (Int,Int) -> [Doc] -> Doc
tableProlog s (m,n) ds =
        columnSep 
    <%> text s 
    <%> columnSep
    <%> columnHeadings m n
    <%> columnSep
    <%> vcat ds
  where
    columnHeadings fsz vsz = 
      text "size" <+> text (pad fsz ' ' "field") <+> text (pad vsz ' ' "value")


columnSep :: Doc
columnSep = text $ replicate 60 '-' 


ppField :: Int -> Int -> Int -> String -> (a -> Doc) -> a -> Doc
ppField n1 n2 sz field_name f a = text sz'  <+> text field_name' <+> f a
  where
    sz'         = pad n1 ' ' (show sz)
    field_name' = pad n2 ' ' field_name

ppHex :: Integral a => Int -> a -> Doc
ppHex n i = text "0x" <> (text $ pad n '0' $ showHex i "")
  

pad :: Int -> Char -> String -> String
pad n ch s | length s < n = replicate (n - length s) ch ++ s
           | otherwise    = s

listDoc :: [Doc] -> Doc
listDoc = brackets . punctuate comma