{-# LANGUAGE OverloadedStrings #-}

module Darcs.Util.Text
    (
    -- * Text construction.
      sentence
    -- * Text formatting.
    , formatText
    , formatParas
    , formatPara
    , chompTrailingNewline
    -- * Text processing
    , breakCommand
    , quote
    , pathlist
    , showCommandLine
    ) where

import Prelude ()
import Darcs.Prelude

import Control.Arrow ( first )
import Data.List ( intercalate )

import Darcs.Util.Printer ( Doc, renderString, quoted, hsep )

sentence :: Doc -> Doc
sentence :: Doc -> Doc
sentence = (Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> ".")

-- |Take a list of paragraphs and format them to the given line length, with
-- a blank line between paragraphs.
formatText :: Int -> [String] -> String
formatText :: Int -> [String] -> String
formatText linelen :: Int
linelen = [String] -> String
unlines ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [String]
formatParas Int
linelen

formatParas :: Int -> [String] -> [String]
formatParas :: Int -> [String] -> [String]
formatParas linelen :: Int
linelen = [String] -> [[String]] -> [String]
forall a. [a] -> [[a]] -> [a]
intercalate [""] ([[String]] -> [String])
-> ([String] -> [[String]]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                      (String -> [String]) -> [String] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map (([String] -> String) -> [[String]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
unwords ([[String]] -> [String])
-> (String -> [[String]]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [[String]]
forall a. Int -> [[a]] -> [[[a]]]
formatPara Int
linelen ([String] -> [[String]])
-> (String -> [String]) -> String -> [[String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words)

-- |Take a list of words and split it up so that each chunk fits into the specified width
-- when spaces are included. Any words longer than the specified width end up in a chunk
-- of their own.
formatPara :: Int -> [[a]] -> [[[a]]]
formatPara :: Int -> [[a]] -> [[[a]]]
formatPara w :: Int
w = [[a]] -> [[[a]]]
forall (t :: * -> *) a. Foldable t => [t a] -> [[t a]]
para'
  where para' :: [t a] -> [[t a]]
para' [] = []
        para' xs :: [t a]
xs = ([t a] -> [[t a]] -> [[t a]]) -> ([t a], [[t a]]) -> [[t a]]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (:) (([t a], [[t a]]) -> [[t a]]) -> ([t a], [[t a]]) -> [[t a]]
forall a b. (a -> b) -> a -> b
$ Int -> [t a] -> ([t a], [[t a]])
para'' Int
w [t a]
xs
        para'' :: Int -> [t a] -> ([t a], [[t a]])
para'' r :: Int
r (x :: t a
x:xs :: [t a]
xs) | Int
w Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
r Bool -> Bool -> Bool
|| t a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
r = ([t a] -> [t a]) -> ([t a], [[t a]]) -> ([t a], [[t a]])
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (t a
xt a -> [t a] -> [t a]
forall a. a -> [a] -> [a]
:) (([t a], [[t a]]) -> ([t a], [[t a]]))
-> ([t a], [[t a]]) -> ([t a], [[t a]])
forall a b. (a -> b) -> a -> b
$ Int -> [t a] -> ([t a], [[t a]])
para'' (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- t a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1) [t a]
xs
        para'' _ xs :: [t a]
xs = ([], [t a] -> [[t a]]
para' [t a]
xs)

breakCommand :: String -> (String, [String])
breakCommand :: String -> (String, [String])
breakCommand s :: String
s = case String -> [String]
words String
s of
                   (arg0 :: String
arg0:args :: [String]
args) -> (String
arg0,[String]
args)
                   [] -> (String
s,[])

chompTrailingNewline :: String -> String
chompTrailingNewline :: String -> String
chompTrailingNewline "" = ""
chompTrailingNewline s :: String
s = if String -> Char
forall a. [a] -> a
last String
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '\n' then String -> String
forall a. [a] -> [a]
init String
s else String
s

-- | Quote a string for screen output.
quote :: String -> String
quote :: String -> String
quote = Doc -> String
renderString (Doc -> String) -> (String -> Doc) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Doc
quoted

-- | Format a list of 'FilePath's as quoted text. It deliberately refuses to
-- use English.andClauses but rather separates the quoted strings only with a
-- space, because this makes it usable for copy and paste e.g. as arguments to
-- another shell command.
pathlist :: [FilePath] -> Doc
pathlist :: [String] -> Doc
pathlist paths :: [String]
paths = [Doc] -> Doc
hsep ((String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
quoted [String]
paths)

-- | Produce a String composed by the elements of [String] each enclosed in
-- double quotes.
showCommandLine :: [String] -> String
showCommandLine :: [String] -> String
showCommandLine strings :: [String]
strings = String -> [String] -> String
showCommandLine' ['"'] [String]
strings
            where showCommandLine' :: String -> [String] -> String
showCommandLine' x :: String
x xs :: [String]
xs =
                        String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate (String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ " " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x) [String]
xs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x