This gives us more accurate string length calculations. In particular, it handles emoji and other scripts properly.
		
			
				
	
	
		
			41 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			41 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
| -- | Calculate the width of String and Text, being aware of wide characters.
 | |
| 
 | |
| module Text.WideString (
 | |
|   -- * Text Builders which keep track of length
 | |
|   WideBuilder(..),
 | |
|   wbUnpack,
 | |
|   wbToText,
 | |
|   wbFromText
 | |
|   ) where
 | |
| 
 | |
| import Data.Text (Text)
 | |
| import qualified Data.Text as T
 | |
| import qualified Data.Text.Lazy as TL
 | |
| import qualified Data.Text.Lazy.Builder as TB
 | |
| import Text.DocLayout (realLength)
 | |
| 
 | |
| 
 | |
| -- | Helper for constructing Builders while keeping track of text width.
 | |
| data WideBuilder = WideBuilder
 | |
|   { wbBuilder :: !TB.Builder
 | |
|   , wbWidth   :: !Int
 | |
|   } deriving (Show)
 | |
| 
 | |
| instance Semigroup WideBuilder where
 | |
|   WideBuilder x i <> WideBuilder y j = WideBuilder (x <> y) (i + j)
 | |
| 
 | |
| instance Monoid WideBuilder where
 | |
|   mempty = WideBuilder mempty 0
 | |
| 
 | |
| -- | Convert a WideBuilder to a strict Text.
 | |
| wbToText :: WideBuilder -> Text
 | |
| wbToText = TL.toStrict . TB.toLazyText . wbBuilder
 | |
| 
 | |
| -- | Convert a strict Text to a WideBuilder.
 | |
| wbFromText :: Text -> WideBuilder
 | |
| wbFromText t = WideBuilder (TB.fromText t) (realLength t)
 | |
| 
 | |
| -- | Convert a WideBuilder to a String.
 | |
| wbUnpack :: WideBuilder -> String
 | |
| wbUnpack = TL.unpack . TB.toLazyText . wbBuilder
 |