packages feed

weatherhs-1.0.0: app/Draw.hs

{-
 - Copyright (C) 2022 Nikola Hadžić
 -
 - This file is part of weatherhs.
 -
 - weatherhs is free software: you can redistribute it and/or modify
 - it under the terms of the GNU General Public License as published by
 - the Free Software Foundation, either version 3 of the License, or
 - (at your option) any later version.
 - 
 - weatherhs is distributed in the hope that it will be useful,
 - but WITHOUT ANY WARRANTY; without even the implied warranty of
 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - GNU General Public License for more details.
 - 
 - You should have received a copy of the GNU General Public License
 - along with weatherhs.  If not, see <https://www.gnu.org/licenses/>.
 -}

module Draw where

import  Data.List.Extra (dropEnd)
import  Text.Printf     (printf)

minTermWidth :: Word
minTermWidth = 5

-- Header nesting level.
data HeaderStrength = H1 | H2 | H3

-- Draws table header.
drawHeader :: Word -> HeaderStrength -> String -> String
drawHeader termWidth headStrength text
    | termWidth < minTermWidth  = error (printf "Minimum terminal width for drawing not satisfied: %u < %u" termWidth minTermWidth)
    | otherwise                 = do
        let textLength = fromIntegral (length text) :: Word
        let textSpace = termWidth - (minTermWidth - 1)
        let excess = if textLength > textSpace then textLength - textSpace else 0
        let position = (termWidth `div` 2 + 1) - ((textLength - excess) `div` 2)

        let sepTopLeft = case headStrength of
                            H1  -> '┏'
                            _   -> '┠'
        let sepTopRight = case headStrength of
                            H1  -> '┓'
                            _   -> '┨'
        let sepHor  = case headStrength of
                        H1  -> '━'
                        H2  -> '─'
                        H3  -> '╌'
        let sepVer = '┃'
        let sepBotLeft = case headStrength of
                            H1  -> '┣'
                            _   -> '┠'
        let sepBotRight = case headStrength of
                            H1  -> '┫'
                            _   -> '┨'

        printf "%s\n%c \o33[%uG%s%s\o33[0m\o33[%uG %c\n%s" (sepTopLeft : (replicate (fromIntegral (termWidth - 2) :: Int) sepHor) ++ [sepTopRight]) sepVer position (case headStrength of
                                                                                                                                                                    H1  -> "\o33[1m\o33[3m"
                                                                                                                                                                    H2  -> "\o33[1m"
                                                                                                                                                                    H3  -> "\o33[3m") ((if excess == 0 then id else (++ "…") . (dropEnd ((fromIntegral excess :: Int) + 1))) text) (termWidth - 1) sepVer (sepBotLeft : (replicate (fromIntegral (termWidth - 2) :: Int) sepHor) ++ [sepBotRight])

-- Draws table field.
drawField :: Word -> String -> String -> String
drawField termWidth name value
    | termWidth < minTermWidth  = error (printf "Minimum terminal width for drawing not satisfied: %u < %u" termWidth minTermWidth)
    | otherwise                 = do
        let nameLength = fromIntegral (length name) :: Word
        let valueLength = fromIntegral (length value) :: Word
        let textLength = nameLength + valueLength + 2
        let textSpace = termWidth - (minTermWidth - 1)
        let excess = if textLength > textSpace then textLength - textSpace else 0
        let inter = if excess == 0 then textSpace - textLength else 0

        let sep = '┃'

        let field = printf "%s: %s%s" name (replicate (fromIntegral inter :: Int) ' ') value
        printf "%c %s %c" sep ((if excess == 0 then id else (++ "…") . (dropEnd ((fromIntegral excess :: Int) + 1))) field) sep

-- Draws table footer.
drawFooter :: Word -> String
drawFooter termWidth
    | termWidth < minTermWidth  = error (printf "Minimum terminal width for drawing not satisfied: %u < %u" termWidth minTermWidth)
    | otherwise                 = '┗' : (replicate (fromIntegral (termWidth - 2) :: Int) '━') ++ "┛"