diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for hchart
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2019
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,132 @@
+chart-cli README
+================
+
+This repo provides a `chart` command-line utility. `chart` is aimed to generate
+basic 2D charts from command line easily.
+
+The `chart` utility is not aimed to give full control over generated charts, or
+to generate all possible types of charts - you may anytime do that by use of
+[gnuplot][1] or [Chart package][2]. This utility, instead, gives you a very
+quick way of generating some most useful types of charts.
+
+Usage example:
+
+```
+$ cat > input.txt
+X	Y1	Y2
+1	1	3
+2	4	6
+3	7	4
+4	5	8
+6	3	2
+^D
+
+$ chart --header -o lines.png input.txt
+```
+
+Result:
+
+![lines.png](https://user-images.githubusercontent.com/284644/63638172-1f134600-c69e-11e9-98ce-4c274ca423f3.png)
+
+Supported chart types for now are:
+
+* Line charts (the default one)
+* Bar charts (clustered and stacked)
+* Area charts
+* Point charts
+
+Other chart types may be added later.
+
+Supported output formats are:
+  
+* PNG (the default one)
+* SVG
+* PS (PostScript)
+* PDF
+
+Output file format is automatically detected by specified output file name. If
+output file name is not specified explicitly, `chart.png` will be used.
+
+Expected input format
+---------------------
+
+Input data are expected to be provided as a series of lines; each line may
+represent either one point to plot, or several points at the same X coordinate.
+
+The first line may optionally represent names of the columns.
+
+Other lines should consist of several numbers. Numbers are separated with a
+delimiter. Default delimiter is TAB characater; you may specify another with
+`-d` command line option.
+
+If only one number per line is provided, then these numbers will be used as Y
+values; for X values, line numbers (starting with 1) will be used.
+
+If more than one number per line is provided, then for most chart types (except
+for bar charts) the first column will be used as X values, and other will be
+used as Y values.
+
+In the first column, date/time values may be provided instead of numbers (to be
+used as values along X axis). Supported date/time formats are:
+
+* DD.MM.YYYY
+* YYYY/MM/DD
+* `12 September 2012'
+* today, tomorrow, yesterday
+* `in 2 days', '3 weeks ago'
+* `last monday', 'next friday'
+* `last month' (1th of this month), `next year' (1th of January of next year)
+
+(thanks to [dates package][3]).
+
+Command-line interface
+----------------------
+
+I'll put it here for quick reference; more actual information is always
+accessible with `chart --help`:
+
+```
+Usage: chart [-o|--output OUTPUT.png] [COMMAND] [-1|--header]
+             [-d|--delimiter CHAR] [-i|--index] [-t|--title TITLE]
+             [-w|--width WIDTH] [-h|--height HEIGHT] [-b|--background COLOR]
+             [-f|--foreground COLOR] [-L|--legend ON|OFF] [INPUT.txt]
+  Make a chart
+
+Available options:
+  -o,--output OUTPUT.png   write output to OUTPUT.png
+  -1,--header              first line contains column headers
+  -d,--delimiter CHAR      specify fields delimiter ('\t' by default)
+  -i,--index               if enabled, treat input data as if there was an
+                           additional first column, containing line numbers,
+                           starting from 1
+  -t,--title TITLE         set chart title to TITLE
+  -w,--width WIDTH         specify chart width, in pixels (default: 800)
+  -h,--height HEIGHT       specify chart height, in pixels (default: 600)
+  -b,--background COLOR    specify background color name (see SVG 1.1 spec)
+  -f,--foreground COLOR    specify foreround color name (see SVG 1.1 spec)
+  -L,--legend ON|OFF       enable or disable the legend (default: True)
+  -h,--help                Show this help text
+
+Available commands:
+  line                     Make a line chart
+  area                     Make an area chart
+  points                   Make a points chart
+  bar                      Make a bar chart
+```
+
+Installation
+------------
+
+Install it by stack:
+
+```
+$ sudo apt-get install stack
+$ git clone https://github.com/portnov/chart-cli.git
+$ cd chart-cli/
+$ stack install
+```
+
+[1]: http://www.gnuplot.info/
+[2]: http://hackage.haskell.org/package/Chart
+[3]: http://hackage.haskell.org/package/dates
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/chart-cli.cabal b/chart-cli.cabal
new file mode 100644
--- /dev/null
+++ b/chart-cli.cabal
@@ -0,0 +1,55 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: bfc69b38044f97f2a32e60cf1bd54c96f8880da1ba3b3b6c1f3525368808b237
+
+name:           chart-cli
+version:        0.1.0.0
+synopsis:       Command-line utility to draw charts from input data easily
+description:    Please see the README on GitHub at <https://github.com/portnov/chart-cli#readme>
+category:       Graphics
+homepage:       https://github.com/portnov/chart-cli#readme
+bug-reports:    https://github.com/portnov/chart-cli/issues
+author:         Ilya V. Portnov
+maintainer:     portnov84@rambler.ru
+copyright:      2019 Ilya V. Portnov
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/portnov/chart-cli
+
+executable chart
+  main-is: Main.hs
+  other-modules:
+      Chart
+      CmdLine
+      Parser
+      Types
+      Paths_chart_cli
+  hs-source-dirs:
+      src
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      Chart
+    , Chart-cairo
+    , attoparsec
+    , base >=4.7 && <5
+    , colour
+    , data-default-class
+    , dates
+    , filepath
+    , hashable
+    , lens
+    , optparse-applicative
+    , text
+    , time
+  default-language: Haskell2010
diff --git a/src/Chart.hs b/src/Chart.hs
new file mode 100644
--- /dev/null
+++ b/src/Chart.hs
@@ -0,0 +1,143 @@
+{-# LANGUAGE RecordWildCards #-}
+
+module Chart where
+
+import Control.Lens
+import qualified Data.Text as T
+import Data.Colour
+import Data.Colour.SRGB
+import Data.Colour.RGBSpace.HSL
+import Data.Word
+import Data.Hashable
+import Data.List
+import Data.Default.Class
+import Graphics.Rendering.Chart
+
+import Types
+
+nameColor :: T.Text -> Colour Double
+nameColor name =
+  let h = fromIntegral (hash name `mod` 255) :: Word8
+      hue = fromIntegral (hash name `mod` 360)
+      r = (fromIntegral h / 255)
+      v = (1 - r) * 0.5 + r*0.9
+
+      hslColor = hsl hue 0.5 v
+  in  sRGB (channelRed hslColor) (channelGreen hslColor) (channelBlue hslColor)
+
+toPairs :: [[Value]] -> [[(Value, Double)]]
+toPairs = transpose . zipWith go [1..]
+  where
+    go i [y] = [(Number (fromIntegral i), toDouble y)]
+    go _ [x, y] = [(x, toDouble y)]
+    go _ (x : ys) = [(x, toDouble y) | y <- ys]
+
+toSeries :: [[Value]] -> [(Value, [Double])]
+toSeries = zipWith go [1..]
+  where
+    go _ (Date dt : ys) = (Date dt, map toDouble ys)
+    go i ys = (Index (PlotIndex i), map toDouble ys)
+
+toAreas :: [[Value]] -> [[(Value, (Double, Double))]]
+toAreas = transpose . go 1
+  where
+    go :: Int -> [[Value]] -> [[(Value, (Double, Double))]]
+    go _ [] = []
+    go i ([y] : rest) = [(Number (fromIntegral i), (0, toDouble y))] : go (i+1) rest
+    go i ((x : ys) : rest) =
+        let runningSums = tail $ scanl (+) 0 $ map toDouble ys
+            pairs = zip (0 : runningSums) runningSums
+        in  [(x, pair) | pair <- pairs] : go (i+1) rest
+
+mkLineStyle :: T.Text -> LineStyle
+mkLineStyle name =
+  line_color .~ opaque (darken 0.2 $ nameColor name) $ def
+
+mkFillStyle :: T.Text -> FillStyle
+mkFillStyle name =
+  fill_color .~ opaque (nameColor name) $ def
+
+mkPointStyle :: T.Text -> PointStyle
+mkPointStyle name =
+    point_color .~ opaque (nameColor name)
+  $ point_border_color .~ opaque (darken 0.2 $ nameColor name)
+  $ point_border_width .~ 1
+  $ point_radius .~ 4
+  $ def
+
+tailOrSingle :: [a] -> [a]
+tailOrSingle [] = []
+tailOrSingle [x] = [x]
+tailOrSingle (x:xs) = xs
+
+convertChart :: ChartConfig -> ChartData -> AnyChart
+convertChart Line cht =
+  LineChart [
+        plot_lines_title .~ T.unpack title
+      $ plot_lines_style .~ mkLineStyle title
+      $ plot_lines_values .~ [pairs]
+      $ def
+    | (pairs, NumberColumn title) <- zip (toPairs (chtValues cht)) (tailOrSingle $ chtColumns cht)
+  ]
+convertChart (Bar {..}) cht =
+  BarChart $
+      plot_bars_titles .~ [T.unpack title | NumberColumn title <- chtColumns cht]
+    $ plot_bars_item_styles .~ [(mkFillStyle title, Just (mkLineStyle title)) | NumberColumn title <- chtColumns cht]
+    $ plot_bars_style .~ barStyle
+    $ plot_bars_values .~ toSeries (chtValues cht)
+    $ def
+convertChart Area cht =
+  AreaChart [
+        plot_fillbetween_title .~ T.unpack title
+      $ plot_fillbetween_style .~ mkFillStyle title
+      $ plot_fillbetween_values .~ area
+      $ def
+    | (area, NumberColumn title) <- zip (toAreas (chtValues cht)) (tailOrSingle $ chtColumns cht)
+  ]
+convertChart Points cht =
+  PointsChart [
+        plot_points_title .~ T.unpack title
+      $ plot_points_style .~ mkPointStyle title
+      $ plot_points_values .~ pairs
+      $ def
+    | (pairs, NumberColumn title) <- zip (toPairs (chtValues cht)) (tail $ chtColumns cht)
+  ]
+
+chartToPlots :: AnyChart -> [Plot Value Double]
+chartToPlots (LineChart plots) = map toPlot plots
+chartToPlots (BarChart plot) = [plotBars plot]
+chartToPlots (AreaChart plots) = map toPlot plots
+chartToPlots (PointsChart plots) = map toPlot plots
+
+makeChart :: ChartConfig -> ChartData -> Layout Value Double
+makeChart chtype cht =
+  let title = chtTitle cht
+      foreground = chtForeground cht
+      background = chtBackground cht
+      setFontStyle = font_color .~ opaque foreground
+      setLineColor = line_color .~ opaque foreground
+      gridStyle = dashedLine 1 [5, 5] $ dissolve 0.5 $ opaque foreground
+      setAxisColor =
+          laxis_style %~ (axis_label_style %~ setFontStyle) .
+                         (axis_line_style %~ setLineColor) .
+                         (axis_grid_style .~ gridStyle)
+      
+      setLegendFont = legend_label_style %~ setFontStyle
+      setBackground = fill_color .~ opaque background
+
+      yAxis = setAxisColor def
+      xAxis = setAxisColor def
+
+      legend = if chtLegend cht
+                 then Just $ setLegendFont $ legend_orientation .~ LORows 4 $ def
+                 else Nothing
+
+  in  layout_title .~ T.unpack title
+        $ layout_background %~ setBackground
+        $ layout_title_style %~ setFontStyle
+        $ layout_x_axis .~ xAxis
+        $ layout_y_axis .~ yAxis
+        $ layout_legend .~ legend
+        $ layout_plots .~ chartToPlots (convertChart chtype cht)
+        $ def
+
diff --git a/src/CmdLine.hs b/src/CmdLine.hs
new file mode 100644
--- /dev/null
+++ b/src/CmdLine.hs
@@ -0,0 +1,152 @@
+
+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
+
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main where
+
+import Control.Lens
+import qualified Data.Text as T
+import Data.Default.Class
+import Graphics.Rendering.Chart
+import Graphics.Rendering.Chart.Backend.Cairo
+import System.Environment
+import System.FilePath
+
+import Types
+import Chart
+import Parser
+import CmdLine
+
+main :: IO ()
+main = do
+  cmd <- parseCmdLine
+--   print cmd
+  let path = cmdInput cmd
+      outPath = cmdOutput cmd
+  let opts = cmdParse cmd
+  cht <- parseFile opts path
+--   print $ toPairs $ chtValues cht
+  
+  let cht' =
+        case cmdTitle cmd of
+          Nothing -> cht
+          Just title -> cht {chtTitle = T.pack title}
+
+      chart = cht' {
+                  chtForeground = cmdForeground cmd
+                , chtBackground = cmdBackground cmd
+                , chtLegend = cmdLegend cmd
+              }
+
+  let width = cmdWidth cmd
+      height = cmdHeight cmd
+      fileOpts = fo_size .~ (width, height)
+                  $ fo_format .~ detectFormat outPath
+                  $ def
+
+  renderableToFile fileOpts outPath $ toRenderable $ makeChart (cmdChart cmd) chart
+  return ()
+
diff --git a/src/Parser.hs b/src/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Parser.hs
@@ -0,0 +1,90 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Parser where
+
+import Control.Monad
+import Data.Colour.Names
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+import qualified Data.Attoparsec.Text as A
+import Data.Dates
+import System.IO.Unsafe (unsafePerformIO)
+
+import Types
+
+now :: DateTime
+now = unsafePerformIO getCurrentDateTime
+
+parseText :: ParseOptions -> T.Text -> T.Text -> Either String ChartData
+parseText opts title text = do
+  let lines = T.lines text
+      splitLine line = T.splitOn (poSeparator opts) line
+
+      inputColsCount = length (splitLine firstLine)
+
+      parseLine :: Int -> T.Text -> Either String [Value]
+      parseLine lineNo line =
+        let items = splitLine line
+        in  if length items == inputColsCount
+            then zipWithM (parseValue lineNo) [1..] items
+            else Left $ "Line " ++ show lineNo ++ ": number of columns is not equal to number of columns in the first line."
+
+      parseValue lineNo colNo s =
+        case A.parseOnly (A.double <* A.endOfInput) s of
+          Right value -> Right $ Number value
+          Left numberErr ->
+            case parseDateTime now (T.unpack s) of
+              Right dt -> Right $ Date $ toLocalTime dt
+              Left dateErr -> Left $ "Line " ++ show lineNo ++ ", column " ++ show colNo ++ ":\n" ++
+                                "Can't parse `" ++ T.unpack s ++
+                                "` as a number: " ++ numberErr ++
+                                ";\nCan't parse it as a date/time value: " ++ show dateErr
+
+      firstLine = head lines
+
+      defHeader n = "Column " <> T.pack (show n)
+
+      dataLines =
+        if poHeader opts
+          then tail lines
+          else lines
+
+  inputValues <- zipWithM parseLine [1..] dataLines
+
+  let values = if poIndex opts
+                  then zipWith (:) (map Index [1..]) inputValues
+                  else inputValues
+      
+      colsCount =
+        if poIndex opts
+          then inputColsCount + 1
+          else inputColsCount
+
+      columnNames =
+        if poHeader opts
+          then splitLine firstLine
+          else map defHeader [0 .. colsCount - 1]
+
+      columns = map NumberColumn columnNames
+
+  return $ ChartData {
+          chtTitle = title
+        , chtColumns = columns
+        , chtBackground = white
+        , chtForeground = black
+        , chtLegend = True
+        , chtValues = values
+      }
+
+parseFile :: ParseOptions -> Maybe FilePath -> IO ChartData
+parseFile opts mbPath = do
+  text <- case mbPath of
+            Nothing -> TIO.getContents
+            Just path -> TIO.readFile path
+  let title = case mbPath of
+                Nothing -> "stdin"
+                Just path -> T.pack path
+  case parseText opts title text of
+    Right chart -> return chart
+    Left err -> fail err
+
diff --git a/src/Types.hs b/src/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Types.hs
@@ -0,0 +1,109 @@
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE StandaloneDeriving #-}
+module Types where
+
+import qualified Data.Text as T
+import Data.Dates
+import Data.Time
+import Data.Time.Calendar
+import Data.Time.LocalTime
+import Data.Colour
+import Graphics.Rendering.Chart
+
+data ParseOptions = ParseOptions {
+      poHeader :: Bool
+    , poSeparator :: T.Text
+    , poIndex :: Bool
+  }
+  deriving (Eq, Show)
+
+data Value =
+    Number Double
+  | Index PlotIndex
+  | Date { toTime :: LocalTime }
+  deriving (Eq, Show, Ord)
+
+toDouble :: Value -> Double
+toDouble (Number x) = x
+toDouble (Index i) = toValue i
+toDouble (Date dt) = error $ "can't convert date/time to double"
+
+toIndex :: Value -> PlotIndex
+toIndex (Number x) = PlotIndex $ round x
+toIndex (Index i) = i
+toINdex (Date dt) = error $ "can't convert date/time to index"
+
+data Column =
+    NumberColumn T.Text
+  | DateColumn T.Text
+  deriving (Eq, Show)
+
+data ChartData = ChartData {
+      chtTitle :: T.Text
+    , chtBackground :: Colour Double
+    , chtForeground :: Colour Double
+    , chtLegend :: Bool
+    , chtColumns :: [Column]
+    , chtValues :: [[Value]]
+  }
+  deriving (Eq, Show)
+
+deriving instance Eq PlotBarsStyle
+
+data ChartConfig =
+    Line
+  | Bar { barStyle :: PlotBarsStyle }
+  | Area
+  | Points
+  deriving (Eq, Show)
+
+data AnyChart =
+    LineChart [PlotLines Value Double]
+  | BarChart (PlotBars Value Double)
+  | AreaChart [PlotFillBetween Value Double]
+  | PointsChart [PlotPoints Value Double]
+
+toLocalTime :: DateTime -> LocalTime
+toLocalTime dt =
+  let localDay = fromGregorian (fromIntegral $ year dt) (month dt) (day dt)
+      time = TimeOfDay (hour dt) (minute dt) (fromIntegral $ second dt)
+  in  LocalTime localDay time
+
+mapAxisData :: (x -> y) -> (y -> x) -> AxisData x -> AxisData y
+mapAxisData to from axis =
+  axis {
+      _axis_viewport = \range x -> _axis_viewport axis range (from x)
+    , _axis_tropweiv = \range d -> to (_axis_tropweiv axis range d)
+    , _axis_ticks = [(to x, d) | (x, d) <- _axis_ticks axis]
+    , _axis_labels = [[(to x, s) | (x, s) <- pairs] | pairs <- _axis_labels axis]
+    , _axis_grid = map to (_axis_grid axis)
+  }
+
+instance PlotValue Value where
+  toValue (Number x) = x
+  toValue (Date dt) = toValue dt
+  toValue (Index i) = toValue i
+
+  fromValue x = Number x
+  
+  autoAxis = \list ->
+    case list of
+      [] -> mapAxisData Number toDouble $ autoAxis $ map toDouble list
+      (Number x : _) -> mapAxisData Number toDouble $ autoAxis $ map toDouble list
+      (Date dt : _) -> mapAxisData Date toTime $ autoAxis $ map toTime list
+      (Index i : _) -> mapAxisData Index toIndex $ autoAxis $ map toIndex list
+
+data CmdLine = CmdLine {
+      cmdOutput :: FilePath
+    , cmdChart :: ChartConfig
+    , cmdParse :: ParseOptions
+    , cmdTitle :: Maybe String
+    , cmdWidth :: Int
+    , cmdHeight :: Int
+    , cmdBackground :: Colour Double
+    , cmdForeground :: Colour Double
+    , cmdLegend :: Bool
+    , cmdInput :: Maybe FilePath
+  }
+  deriving (Show)
+
