filediff 0.1.0.1 → 0.1.0.2
raw patch · 4 files changed
+50/−39 lines, 4 filesdep +data-defaultPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
Dependencies added: data-default
API changes (from Hackage documentation)
+ Filediff.Sequence: instance Default (SeqDiff a)
+ Filediff.Types: instance Default Diff
Files
- filediff.cabal +2/−2
- src/Filediff.hs +10/−10
- src/Filediff/Sequence.hs +27/−21
- src/Filediff/Types.hs +11/−6
filediff.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: filediff-version: 0.1.0.1+version: 0.1.0.2 synopsis: Diffing and patching module description: `filediff` is a Haskell library for creating diffs, and applying diffs to files and directories. homepage: https://github.com/bgwines/filediff@@ -23,7 +23,7 @@ exposed-modules: Filediff, Filediff.Types, Filediff.Sequence other-modules: Filediff.Utils -- other-extensions:- build-depends: base >=4.7 && <4.8, mtl, time, directory, either, transformers, data-memocombinators, tasty, tasty-hunit, Zora >=1.1.22, text+ build-depends: base >=4.7 && <4.8, mtl, time, directory, either, transformers, data-memocombinators, Zora >=1.1.22, text, data-default, tasty, tasty-hunit hs-source-dirs: src default-language: Haskell2010
src/Filediff.hs view
@@ -45,12 +45,12 @@ -- * basic operations -- | /O(mn)/. Compute the difference between the two files (more--- | specifically, the minimal number of changes to make to transform the--- | file residing at the location specified by the first--- | parameter into the second). Throws an exception if either or both of--- | the parameters point to a directory, not a file.--- |--- | Files are allowed to not exist at either or both of the parameters.+-- specifically, the minimal number of changes to make to transform the+-- file residing at the location specified by the first+-- parameter into the second). Throws an exception if either or both of+-- the parameters point to a directory, not a file.+-- +-- Files are allowed to not exist at either or both of the parameters. diffFiles :: FilePath -> FilePath -> IO Filediff diffFiles a b = do aIsDir <- D.doesDirectoryExist a@@ -68,10 +68,10 @@ , linediff = linediff } -- | Compute the difference between the two directories (more--- | specifically, the minimal number of changes to make to transform the--- | directory residing at the location specified by the first--- | parameter into the second). Throws an exception if either or both of--- | the parameters point to a file, not a directory.+-- specifically, the minimal number of changes to make to transform the+-- directory residing at the location specified by the first+-- parameter into the second). Throws an exception if either or both of+-- the parameters point to a file, not a directory. diffDirectories :: FilePath -> FilePath -> IO Diff diffDirectories a b = do aIsFile <- D.doesFileExist a
src/Filediff/Sequence.hs view
@@ -16,6 +16,8 @@ import GHC.Generics +import Data.Default+ import Data.MemoCombinators.Class (MemoTable, table) import qualified Data.MemoCombinators as Memo @@ -27,14 +29,18 @@ -- * data types --- | Diff between two sequences. `fst` represents the indices--- | at which to delete, and `snd` represents the indices and--- | contents to add.+-- | Diff between two lists. `dels` represents the indices+-- at which to delete, and `adds` represents the indices and+-- contents to add. data SeqDiff a = SeqDiff { dels :: [Int] , adds :: [(Int, a)] } deriving (Show, Eq, Generic) +instance Default (SeqDiff a) where+ def :: SeqDiff a+ def = SeqDiff [] []+ instance (Eq a, MemoTable a) => Monoid (SeqDiff a) where mempty :: SeqDiff a mempty = SeqDiff [] []@@ -106,9 +112,9 @@ -- * list operations -- | returns (to delete, to add)--- |--- | > diffSequences "abcdefg" "wabxyze"--- | SeqDiff {dels = [2,3,5,6], adds = [(0,'w'),(3,'x'),(4,'y'),(5,'z')]}+-- +-- > diffSequences "abcdefg" "wabxyze"+-- SeqDiff {dels = [2,3,5,6], adds = [(0,'w'),(3,'x'),(4,'y'),(5,'z')]} diffSequences :: forall a. (Eq a, MemoTable a) => [a] -> [a] -> SeqDiff a diffSequences a b = SeqDiff (nonSubsequenceIndices common a)@@ -126,10 +132,10 @@ map (\i -> (i, super !! i)) $ nonSubsequenceIndices sub super -- | > diffSequences "abcdefg" "wabxyze"--- | SeqDiff {dels = [2,3,5,6], adds = [(0,'w'),(3,'x'),(4,'y'),(5,'z')]}--- |--- | > applySequenceDiff it "abcdefg"--- | "wabxyze"+-- SeqDiff {dels = [2,3,5,6], adds = [(0,'w'),(3,'x'),(4,'y'),(5,'z')]}+-- +-- > applySequenceDiff it "abcdefg"+-- "wabxyze" applySequenceDiff :: forall a. (Eq a) => SeqDiff a -> [a] -> [a] applySequenceDiff (SeqDiff dels adds) = insertAtProgressiveIndices adds . removeAtIndices dels@@ -154,8 +160,8 @@ -- optimization: hash lines -- | Compute the longest common (potentially noncontiguous) subsequence--- | between two sequences. Element type is fixed because memoization--- | requires a static type.+-- between two sequences. Element type is fixed because memoization+-- requires a static type. longestCommonSubsequence :: forall a. (MemoTable a, Eq a) => [a] -> [a] -> [a] longestCommonSubsequence@@ -181,10 +187,10 @@ caseY = longestCommonSubsequence (x:xs) ys -- | When `sub` is a (not necessarily contiguous) subsequence of `super`,--- | get the index at which each element of `sub` appears. E.g.--- |--- | > subsequenceIndices "abe" "abcdefg"--- | [0,1,4]+-- get the index at which each element of `sub` appears. E.g.+-- +-- > subsequenceIndices "abe" "abcdefg"+-- [0,1,4] subsequenceIndices :: (Eq a) => [a] -> [a] -> [Int] subsequenceIndices [] _ = [] subsequenceIndices _ [] = error "`sub` was not a subsequence of `super`"@@ -194,16 +200,16 @@ else map succ (subsequenceIndices sub super') -- | When `sub` is a (not necessarily contiguous) subsequence of `super`,--- | get the indices at which elements of `sub` do *not* appear. E.g.--- |--- | > nonSubsequenceIndices "abe" "abcdefg"--- | [2,3,5,6]+-- get the indices at which elements of `sub` do *not* appear. E.g.+-- +-- > nonSubsequenceIndices "abe" "abcdefg"+-- [2,3,5,6] nonSubsequenceIndices :: (Eq a) => [a] -> [a] -> [Int] nonSubsequenceIndices sub super = [0..(length super - 1)] \\ (subsequenceIndices sub super) -- | /O(n)/. `indices` parameter *must* be sorted in increasing order,--- | and indices must all exist+-- and indices must all exist removeAtIndices :: forall a. [Int] -> [a] -> [a] removeAtIndices = removeAtIndices' 0 where
src/Filediff/Types.hs view
@@ -11,6 +11,8 @@ import GHC.Generics +import Data.Default+ import qualified Data.Text as T import Data.List (intersect, sortBy)@@ -24,10 +26,10 @@ import Data.MemoCombinators.Class (MemoTable, table, memoize) -- | The basic data type for a difference between two files. The--- | `FilePath` is the "base" file in the base-comp comparison, and--- | is the file to which the patch will be applied. Deletions: a list--- | of indices at which to remove elements. Additions: each line to add--- | comes with the index at which it will eventually reside.+-- `FilePath` is the "base" file in the base-comp comparison, and+-- is the file to which the patch will be applied. Deletions: a list+-- of indices at which to remove elements. Additions: each line to add+-- comes with the index at which it will eventually reside. data Filediff = Filediff { base :: FilePath, comp :: FilePath,@@ -64,9 +66,12 @@ then base a `compare` base b else comp a `compare` comp b +instance Default Diff where+ def :: Diff+ def = Diff []+ instance MemoTable T.Text where- -- :: (ByteString -> r) -> ByteString -> r- -- table :: Memo ByteString+ table :: Memo T.Text table = wrap T.pack T.unpack table instance Monoid Diff where