yi-rope 0.4.1.0 → 0.5.0.0
raw patch · 2 files changed
+73/−26 lines, 2 filesdep +bytestringdep +charsetdetect-aedep +text-icuPVP ok
version bump matches the API change (PVP)
Dependencies added: bytestring, charsetdetect-ae, text-icu
API changes (from Hackage documentation)
- Yi.Rope: readFile' :: FilePath -> (Text -> Int) -> IO YiString
+ Yi.Rope: data ConverterName
+ Yi.Rope: instance Binary ConverterName
+ Yi.Rope: instance Eq ConverterName
+ Yi.Rope: instance Ord ConverterName
+ Yi.Rope: instance Read ConverterName
+ Yi.Rope: instance Show ConverterName
+ Yi.Rope: instance Typeable ConverterName
+ Yi.Rope: writeFileUsingText :: FilePath -> YiString -> IO ()
+ Yi.Rope: writeFileWithConverter :: FilePath -> YiString -> Converter -> IO ()
- Yi.Rope: readFile :: FilePath -> IO YiString
+ Yi.Rope: readFile :: FilePath -> IO (Either Text (YiString, ConverterName))
- Yi.Rope: writeFile :: FilePath -> YiString -> IO ()
+ Yi.Rope: writeFile :: FilePath -> YiString -> ConverterName -> IO ()
Files
- src/Yi/Rope.hs +69/−25
- yi-rope.cabal +4/−1
src/Yi/Rope.hs view
@@ -50,7 +50,8 @@ Yi.Rope.replicate, Yi.Rope.replicateChar, -- * IO- Yi.Rope.readFile, Yi.Rope.readFile', Yi.Rope.writeFile,+ ConverterName, Yi.Rope.readFile, Yi.Rope.writeFile,+ Yi.Rope.writeFileUsingText, Yi.Rope.writeFileWithConverter, -- * Escape latches to underlying content. Note that these are safe -- to use but it does not mean they should.@@ -58,10 +59,13 @@ ) where +import Codec.Text.Detect (detectEncodingName) import Control.Applicative ((<$>)) import Control.DeepSeq import Data.Binary-import Data.Char (isSpace)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BSL+import Data.Char (isSpace, toLower) import Data.Default import qualified Data.FingerTree as T import Data.FingerTree hiding (null, empty, reverse, split)@@ -70,7 +74,8 @@ import Data.Monoid import Data.String (IsString(..)) import qualified Data.Text as TX-import qualified Data.Text.IO as TF (writeFile, readFile)+import Data.Text.ICU.Convert+import qualified Data.Text.IO as TF (writeFile) import Data.Typeable import Prelude hiding (drop) @@ -104,6 +109,7 @@ -> YiChunk -> YiChunk overChunk f (Chunk l t) = Chunk l (f t) +-- | Counts number of newlines in the given 'TX.Text'. countNl :: TX.Text -> Int countNl = TX.count (TX.pack "\n") @@ -638,34 +644,72 @@ put = put . toString get = Yi.Rope.fromString <$> get --- | Write a 'YiString' into the given file. It's up to the user to--- handle exceptions.-writeFile :: FilePath -> YiString -> IO ()-writeFile f = TF.writeFile f . toText+-- | 'ConverterName' is used to convey information about the+-- underlying 'Converter' used within the buffer to encode and decode+-- text. It is mostly here due to the lack of 'Binary' instance for+-- 'Converter' itself.+newtype ConverterName = CN String deriving (Show, Eq, Ord, Read, Typeable) --- | Reads file into the rope, using 'fromText'. It's up to the user--- to handle exceptions.-readFile :: FilePath -> IO YiString-readFile f = fromText <$> TF.readFile f+-- | Simply 'put's/'get's the underlying 'String'.+instance Binary ConverterName where+ put (CN s) = put s+ get = CN <$> get --- | A version of 'readFile' which allows for arbitrary chunk size to--- start with.+-- | Writes the given 'YiString' to the given file, according to the+-- 'Converter' specified by 'ConverterName'. You can obtain a+-- 'ConverterName' through 'readFile'. If you have a 'Converter', use+-- 'writeFileWithConverter' instead. ----- For example, @readFile' foo ((/ 2) . 'TX.length')@ would produce--- chunks that are half the size of the read in text: whether that's a--- good idea depends on situation.+-- If you don't care about the encoding used such as when creating a+-- brand new file, you can use 'writeFileUsingText'. ----- Note that if this number ends up as @< 1@, 'defaultChunkSize' will--- be used instead.+-- It's up to the user to handle exceptions.+writeFile :: FilePath -> YiString -> ConverterName -> IO ()+writeFile f s (CN cn) = open cn (Just True) >>= writeFileWithConverter f s++-- | As 'writeFile' but using the provided 'Converter' rather than+-- creating one from a 'ConverterName'. -- -- It's up to the user to handle exceptions.-readFile' :: FilePath -> (TX.Text -> Int) -> IO YiString-readFile' f l = do- c <- TF.readFile f- let l' = case l c of- x | x < 1 -> defaultChunkSize- | otherwise -> x- return $ fromText' l' c+writeFileWithConverter :: FilePath -> YiString -> Converter -> IO ()+writeFileWithConverter f s c = BS.writeFile f (fromUnicode c $ toText s)++-- | Write a 'YiString' into the given file. This function uses+-- 'TF.writeFile' to do the writing: if you have special needs for+-- preserving encoding/decoding, use 'writeFile' instead.+--+-- It's up to the user to handle exceptions.+writeFileUsingText :: FilePath -> YiString -> IO ()+writeFileUsingText f = TF.writeFile f . toText+++-- | Reads file into the rope, also returning the 'ConverterName' that+-- was used for decoding. You should resupply this to 'writeFile' if+-- you're aiming to preserve the original encoding.+--+-- If we fail to guess the encoding used, error message is given+-- instead.+--+-- It is up to the user to handle exceptions not directly related to+-- character decoding.+readFile :: FilePath -> IO (Either TX.Text (YiString, ConverterName))+readFile fp = do+ cs <- BSL.readFile fp+ case detectEncodingName cs of+ Nothing -> return . Left . TX.pack $ "Could not guess the encoding of " <> fp+ Just enc -> do+ let downcase = Prelude.map toLower+ ke = if enc == "ASCII"+ then Just "UTF-8"+ else if downcase enc `elem` Prelude.map downcase converterNames+ then Just enc else Nothing+ case ke of+ Nothing -> return . Left . TX.pack $+ "Don't know how to decode as " <> enc+ Just s -> do+ c <- open s (Just True)+ let st = BSL.toStrict cs+ return $ Right (fromText . toUnicode c $ st, CN $ getName c) -- | Filters the characters from the underlying string. --
yi-rope.cabal view
@@ -1,5 +1,5 @@ name: yi-rope-version: 0.4.1.0+version: 0.5.0.0 synopsis: A rope data structure used by Yi description: A rope data structure used by Yi license: GPL-2@@ -22,10 +22,13 @@ build-depends: base >=4.5 && <5 , binary+ , bytestring+ , charsetdetect-ae , data-default , deepseq , fingertree , text+ , text-icu hs-source-dirs: src default-language: Haskell2010