packages feed

chart-cli-0.1.0.0: src/CmdLine.hs

module CmdLine where

import qualified Data.Text as T
import Data.Char (toUpper)
import Data.Colour
import Data.Colour.Names
import Options.Applicative
import Graphics.Rendering.Chart
import Graphics.Rendering.Chart.Backend.Cairo
import System.FilePath

import Types

pCmdLine :: Parser CmdLine
pCmdLine =
    CmdLine
      <$> strOption
            ( long "output"
              <> short 'o'
              <> metavar "OUTPUT.png"
              <> value "chart.png"
              <> help "write output to OUTPUT.png"
            )
      <*> pChart
      <*> pParseOpts
      <*> (optional $ strOption
            ( long "title"
              <> short 't'
              <> metavar "TITLE"
              <> help "set chart title to TITLE"
            )
          )
      <*> option auto
            ( long "width"
              <> short 'w'
              <> value 800
              <> metavar "WIDTH"
              <> showDefault
              <> help "specify chart width, in pixels"
            )
      <*> option auto
            ( long "height"
              <> short 'h'
              <> value 600
              <> metavar "HEIGHT"
              <> showDefault
              <> help "specify chart height, in pixels"
            )
      <*> option colour
            ( long "background"
              <> short 'b'
              <> value white
              <> metavar "COLOR"
              <> help "specify background color name (see SVG 1.1 spec)"
            )
      <*> option colour
            ( long "foreground"
              <> short 'f'
              <> value black
              <> metavar "COLOR"
              <> help "specify foreround color name (see SVG 1.1 spec)"
            )
      <*> option bool
            ( long "legend"
              <> short 'L'
              <> value True
              <> metavar "ON|OFF"
              <> showDefault
              <> help "enable or disable the legend"
            )
      <*> (optional $ strArgument (metavar "INPUT.txt"))

colour :: ReadM (Colour Double)
colour = maybeReader readColourName

bool :: ReadM Bool
bool = maybeReader $ \str -> 
  case map toUpper str of
    "TRUE" -> Just True
    "ON" -> Just True
    "YES" -> Just True
    "Y" -> Just True
    "FALSE" -> Just False
    "OFF" -> Just False
    "NO" -> Just False
    "N" -> Just False
    _ -> Nothing

pChart :: Parser ChartConfig
pChart =
    hsubparser (
           command "line" (info (pure Line) (progDesc "Make a line chart"))
        <> command "area" (info (pure Area) (progDesc "Make an area chart"))
        <> command "points" (info (pure Points) (progDesc "Make a points chart"))
        <> command "bar" (info pBar (progDesc "Make a bar chart"))
      )
  <|> pure Line

pBar :: Parser ChartConfig
pBar =
  Bar
    <$> (    flag' BarsStacked
                (long "stack"
                  <> help "stack bars of different columns on top of each other (by default)")
         <|> flag' BarsClustered
                (long "cluster"
                  <> help "place bars of different columns near each other")
         <|> pure BarsStacked
        )

pParseOpts :: Parser ParseOptions
pParseOpts =
  ParseOptions
    <$> switch
          ( long "header"
            <> short '1'
            <> help "first line contains column headers"
          )
    <*> (T.pack <$> strOption
          ( long "delimiter"
            <> short 'd'
            <> metavar "CHAR"
            <> value "\t"
            <> help "specify fields delimiter ('\\t' by default)"
          )
        )
    <*> switch
          ( long "index"
            <> short 'i'
            <> showDefault
            <> help "if enabled, treat input data as if there was an additional first column, containing line numbers, starting from 1"
          )
          
parseCmdLine :: IO CmdLine
parseCmdLine = execParser opts
  where
    opts = info (pCmdLine <**> helper)
             ( fullDesc
               <> progDesc "Make a chart"
               <> header "chart - plot charts from input data"
             )

detectFormat :: FilePath -> FileFormat
detectFormat path =
  case map toUpper (takeExtension path) of
    ".PNG" -> PNG
    ".SVG" -> SVG
    ".PS" -> PS
    ".PDF" -> PDF
    ext -> error $ "unsupported output file format: " ++ ext