packages feed

diohsc-0.1.14.3: Pager.hs

-- This file is part of Diohsc
-- Copyright (C) 2020 Martin Bays <mbays@sdf.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of version 3 of the GNU General Public License as
-- published by the Free Software Foundation, or any later version.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see http://www.gnu.org/licenses/.

{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}

module Pager where

import           Control.Exception        (throw)
import           Control.Monad            (when)
import           Control.Monad.IO.Class   (MonadIO, liftIO)
import           Data.Char                (toLower)
import           Data.Maybe               (fromMaybe, isJust)
import           Safe                     (readMay)
import           System.IO                (hFlush, stdout)

import qualified Data.Text.Lazy           as T
import qualified Data.Text.Lazy.IO        as T
import qualified System.Console.Haskeline as HL

import           ANSIColour
import           Prompt

printLinesPaged :: MonadIO m => Int -> Int -> Int -> (String -> m ()) -> [T.Text] -> m ()
printLinesPaged wrapCol termWidth perpage doCmd
    | perpage <= 0 = \_ -> pure ()
    | otherwise = printLinesPaged' perpage Nothing
    where
    printLinesPaged' n mcol [] | n > 0 =
        when (isJust mcol) . liftIO $ putStrLn ""
    printLinesPaged' n mcol (l:ls) | n > 0 = do
        let physLines = (+ 1) . max 0 $ (visibleLength l - 1) `div` termWidth
            endCol = visibleLength l `mod` termWidth
        when (isJust mcol) . liftIO $ putStrLn ""
        liftIO $ T.putStr l >> hFlush stdout
        printLinesPaged' (n - physLines) (Just endCol) ls
    printLinesPaged' _ mcol ls = do
        let col = fromMaybe 0 mcol
        liftIO . T.putStr $ T.replicate (fromIntegral $ wrapCol - col) " "
        c <- liftIO . promptChar $ drop (col + 4 - termWidth) "  --"
        liftIO $ putStrLn ""
        case toLower <$> c of
            Nothing -> throw HL.Interrupt
            Just 'q' -> return ()
            Just c' | c' == '\n' || c' == '\r' -> return ()
            Just c' | Just m <- readMay (c':""), m > 0 -> printLinesPaged' m Nothing ls
            Just 'c' -> printLinesPaged' 9999 Nothing ls
            Just 'h' -> printLinesPaged' (perpage `div` 2) Nothing ls
            Just c' | c' == ':' || c' == '>' -> do
                liftIO (promptLine "> ") >>= \case
                    Just (Just cmd) -> doCmd cmd
                    _               -> pure ()
                printLinesPaged' 0 Nothing ls
            _ -> printLinesPaged' perpage Nothing ls