word-wrap 0.3 → 0.3.1
raw patch · 4 files changed
+50/−25 lines, 4 files
Files
- CHANGELOG.md +7/−0
- src/Text/Wrap.hs +31/−22
- tests/Main.hs +11/−2
- word-wrap.cabal +1/−1
CHANGELOG.md view
@@ -1,4 +1,11 @@ +0.3.1+=====++Bug fixes:+ * Fix inconsistent long token breaking (long tokens anywhere but the+ beginning of a line)+ 0.3 ===
src/Text/Wrap.hs view
@@ -7,6 +7,7 @@ ) where +import Data.Monoid ((<>)) import Data.Char (isSpace) import qualified Data.Text as T @@ -74,14 +75,8 @@ wrapLine settings limit t = let go [] = [T.empty] go [WS _] = [T.empty]- go [tok] = if breakLongWords settings- then let (h, tl) = T.splitAt limit $ tokenContent tok- in if T.null tl- then [h]- else h : go [NonWS tl]- else [tokenContent tok] go ts =- let (firstLine, maybeRest) = breakTokens limit ts+ let (firstLine, maybeRest) = breakTokens settings limit ts firstLineText = T.stripEnd $ T.concat $ fmap tokenContent firstLine in case maybeRest of Nothing -> [firstLineText]@@ -98,35 +93,49 @@ -- right, return Just those too (or Nothing if there weren't any). If -- this breaks a sequence at at point where the next token after the -- break point is whitespace, that whitespace token is removed.-breakTokens :: Int -> [Token] -> ([Token], Maybe [Token])-breakTokens _ [] = ([], Nothing)-breakTokens _ [t] = ([t], Nothing)-breakTokens limit ts =+breakTokens :: WrapSettings -> Int -> [Token] -> ([Token], Maybe [Token])+breakTokens _ _ [] = ([], Nothing)+breakTokens settings limit ts = -- Take enough tokens until we reach the point where taking more -- would exceed the line length.- let go _ [] = []- -- If the line starts with a token that itself exceeds the+ let go _ [] = ([], [])+ -- If the line contains a single token that itself exceeds the -- limit, just take that single token as the only one on this -- line.- go acc (tok:_) | acc == 0 && tokenLength tok > limit = [tok]+ go acc (tok:rest) | acc == 0 && tokenLength tok > limit =+ case breakLongWords settings of+ False -> ([tok], rest)+ True ->+ case tok of+ WS _ -> ([], rest)+ NonWS _ ->+ let (h, tl) = T.splitAt limit (tokenContent tok)+ in ([NonWS h], tokenize tl <> rest) -- Otherwise take a token if its length plus the accumulator -- doesn't exceed the limit. go acc (tok:toks) = if tokenLength tok + acc <= limit- then tok : go (acc + tokenLength tok) toks- else []+ then let (nextAllowed, nextDisallowed) = go (acc + tokenLength tok) toks+ in (tok : nextAllowed, nextDisallowed)+ else if not $ breakLongWords settings+ then ([], (tok:toks))+ else case tok of+ WS _ -> ([], toks)+ NonWS _ ->+ let (h, tl) = T.splitAt (limit - acc) (tokenContent tok)+ in ([NonWS h], tokenize tl <> toks) - -- Allowed tokens are the ones we keep on this line.- allowed = go 0 ts- -- The rest go on the next line, to be wrapped again.- rest = maybeTrim $ drop (length allowed) ts+ -- Allowed tokens are the ones we keep on this line. The rest go+ -- on the next line, to be wrapped again.+ (allowed, disallowed') = go 0 ts+ disallowed = maybeTrim disallowed' -- Trim leading whitespace on wrapped lines. maybeTrim [] = [] maybeTrim (WS _:toks) = toks maybeTrim toks = toks - result = if null rest+ result = if null disallowed then (allowed, Nothing)- else (allowed, Just rest)+ else (allowed, Just disallowed) in result
tests/Main.hs view
@@ -39,5 +39,14 @@ it "breaks long non-whitespace tokens" $ do let s = defaultWrapSettings { breakLongWords = True }- wrapTextToLines s 7 "HelloCrazyWorld!"- `shouldBe` ["HelloCr", "azyWorl", "d!"]+ wrapTextToLines s 7 "HelloCrazyWorld!\nReallyLong Token"+ `shouldBe` ["HelloCr", "azyWorl", "d!", "ReallyL", "ong Tok", "en"]++ it "breaks long non-whitespace tokens and indents" $ do+ let s = defaultWrapSettings { breakLongWords = True+ , preserveIndentation = True+ }+ wrapTextToLines s 7 " HelloCrazyWorld!\n ReallyLong Token"+ `shouldBe` [ " Hello", " Crazy", " World", " !"+ , " Reall", " yLong", " Token"+ ]
word-wrap.cabal view
@@ -1,5 +1,5 @@ name: word-wrap-version: 0.3+version: 0.3.1 synopsis: A library for word-wrapping description: A library for wrapping long lines of text. license: BSD3