lib: Correctly strip ansi sequences with no numbers/semicolons.
This commit is contained in:
parent
1fb6f17bb2
commit
600dab3976
@ -50,8 +50,8 @@ module Hledger.Utils.String (
|
|||||||
|
|
||||||
import Data.Char (isDigit, isSpace, toLower, toUpper)
|
import Data.Char (isDigit, isSpace, toLower, toUpper)
|
||||||
import Data.List (intercalate, transpose)
|
import Data.List (intercalate, transpose)
|
||||||
import Text.Megaparsec (Parsec, (<|>), (<?>), between, many, noneOf, oneOf,
|
import Text.Megaparsec (Parsec, (<|>), (<?>), anySingle, between, many, noneOf,
|
||||||
parseMaybe, sepBy, takeWhile1P)
|
oneOf, parseMaybe, sepBy, takeWhileP, try)
|
||||||
import Text.Megaparsec.Char (char, string)
|
import Text.Megaparsec.Char (char, string)
|
||||||
import Text.Printf (printf)
|
import Text.Printf (printf)
|
||||||
|
|
||||||
@ -337,12 +337,18 @@ takeWidth w (c:cs) | cw <= w = c:takeWidth (w-cw) cs
|
|||||||
strWidth :: String -> Int
|
strWidth :: String -> Int
|
||||||
strWidth = maximum . (0:) . map (foldr (\a b -> charWidth a + b) 0) . lines . stripAnsi
|
strWidth = maximum . (0:) . map (foldr (\a b -> charWidth a + b) 0) . lines . stripAnsi
|
||||||
|
|
||||||
|
-- | Strip ANSI escape sequences from a string.
|
||||||
|
--
|
||||||
|
-- >>> stripAnsi "\ESC[31m-1\ESC[m"
|
||||||
|
-- "-1"
|
||||||
stripAnsi :: String -> String
|
stripAnsi :: String -> String
|
||||||
stripAnsi s = maybe s concat $ parseMaybe (many $ takeWhile1P Nothing (/='\ESC') <|> "" <$ ansi) s
|
stripAnsi s = case parseMaybe (many $ "" <$ try ansi <|> pure <$> anySingle) s of
|
||||||
|
Nothing -> error "Bad ansi escape" -- PARTIAL: should not happen
|
||||||
|
Just xs -> concat xs
|
||||||
where
|
where
|
||||||
-- This parses lots of invalid ANSI escape codes, but that should be fine
|
-- This parses lots of invalid ANSI escape codes, but that should be fine
|
||||||
ansi = string "\ESC[" *> digitSemicolons *> suffix <?> "ansi" :: Parsec CustomErr String Char
|
ansi = string "\ESC[" *> digitSemicolons *> suffix <?> "ansi" :: Parsec CustomErr String Char
|
||||||
digitSemicolons = takeWhile1P Nothing (\c -> isDigit c || c == ';')
|
digitSemicolons = takeWhileP Nothing (\c -> isDigit c || c == ';')
|
||||||
suffix = oneOf ['A', 'B', 'C', 'D', 'H', 'J', 'K', 'f', 'm', 's', 'u']
|
suffix = oneOf ['A', 'B', 'C', 'D', 'H', 'J', 'K', 'f', 'm', 's', 'u']
|
||||||
|
|
||||||
-- | Get the designated render width of a character: 0 for a combining
|
-- | Get the designated render width of a character: 0 for a combining
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user