module CabalGild.Unstable.Type.Line where

import qualified CabalGild.Unstable.Type.Chunk as Chunk
import qualified Data.ByteString as ByteString
import qualified Distribution.Compat.Lens as Lens

-- | A line of text, which is made up of a chunk and an indent level.
data Line = Line
  { -- | Number of times the chunk should be indented.
    Line -> Int
indent :: Int,
    Line -> Chunk
chunk :: Chunk.Chunk
  }
  deriving (Line -> Line -> Bool
(Line -> Line -> Bool) -> (Line -> Line -> Bool) -> Eq Line
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Line -> Line -> Bool
== :: Line -> Line -> Bool
$c/= :: Line -> Line -> Bool
/= :: Line -> Line -> Bool
Eq, Int -> Line -> ShowS
[Line] -> ShowS
Line -> String
(Int -> Line -> ShowS)
-> (Line -> String) -> ([Line] -> ShowS) -> Show Line
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Line -> ShowS
showsPrec :: Int -> Line -> ShowS
$cshow :: Line -> String
show :: Line -> String
$cshowList :: [Line] -> ShowS
showList :: [Line] -> ShowS
Show)

-- | A lens for the 'chunk' field.
chunkLens :: Lens.Lens' Line Chunk.Chunk
chunkLens :: Lens' Line Chunk
chunkLens Chunk -> f Chunk
f Line
s = (Chunk -> Line) -> f Chunk -> f Line
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Chunk
a -> Line
s {chunk = a}) (f Chunk -> f Line) -> (Chunk -> f Chunk) -> Chunk -> f Line
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk -> f Chunk
f (Chunk -> f Line) -> Chunk -> f Line
forall a b. (a -> b) -> a -> b
$ Line -> Chunk
chunk Line
s

-- | An empty line, which is an empty chunk with no indentation.
empty :: Line
empty :: Line
empty =
  Line
    { indent :: Int
indent = Int
0,
      chunk :: Chunk
chunk = Chunk
forall a. Monoid a => a
mempty
    }

-- | Returns 'True' if the line's chunk is empty.
isEmpty :: Line -> Bool
isEmpty :: Line -> Bool
isEmpty = Chunk -> Bool
Chunk.isEmpty (Chunk -> Bool) -> (Line -> Chunk) -> Line -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Line -> Chunk
chunk

-- | Converts a line to a 'ByteString' by indenting the chunk.
toByteString :: Line -> ByteString.ByteString
toByteString :: Line -> ByteString
toByteString Line
l =
  if Line -> Bool
isEmpty Line
l
    then ByteString
ByteString.empty
    else
      ByteString -> ByteString -> ByteString
forall a. Monoid a => a -> a -> a
mappend (Int -> Word8 -> ByteString
ByteString.replicate (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Line -> Int
indent Line
l) Word8
0x20)
        (ByteString -> ByteString)
-> (Chunk -> ByteString) -> Chunk -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk -> ByteString
Chunk.value
        (Chunk -> ByteString) -> Chunk -> ByteString
forall a b. (a -> b) -> a -> b
$ Line -> Chunk
chunk Line
l