nix-diff 1.0.13 → 1.0.14
raw patch · 3 files changed
+108/−24 lines, 3 files
Files
- CHANGELOG.md +36/−0
- nix-diff.cabal +2/−1
- src/Main.hs +70/−23
+ CHANGELOG.md view
@@ -0,0 +1,36 @@+1.0.14++* [Improve whitespace handling](https://github.com/Gabriel439/nix-diff/pull/40)+ * `--word-oriented` now treats all whitespace characters as word+ boundaries instead of just spaces++ This matches the behavior of `Prelude.words`++ * `--word-oriented` no longer highlights the intervening spaces between+ words++ This is for consistency with `--line-oriented`, which doesn't+ highlight the intervening spaces between lines. Also, you could argue+ that if the user specifies `--word-oriented` then they want all new+ tokens to be highlighted on a word-by-word basis.++ * `--line-oriented` now no longer introduces a trailing newline at the+ end of a newline-free segment of text++ * More generally, both `--word-oriented` and `--newline-oriented`+ exactly preserve the original whitespace that was used for word or+ line boundaries.++1.0.13++* [Add new `--word-oriented` mode, which is now the new default mode](https://github.com/Gabriel439/nix-diff/pull/38)+ * This now diffs on word boundaries instead of line-boundaries++1.0.12++* [Use "patience" diff algorithm](https://github.com/Gabriel439/nix-diff/pull/33)+ * This improves the quality of the diff++1.0.11++* [Add support for diffing input sources](https://github.com/Gabriel439/nix-diff/pull/30)
nix-diff.cabal view
@@ -1,5 +1,5 @@ name: nix-diff-version: 1.0.13+version: 1.0.14 synopsis: Explain why two Nix derivations differ description: This package provides a @nix-diff@ executable which explains why two Nix derivations (i.e. @*.drv@ files)@@ -15,6 +15,7 @@ tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.8.3 cabal-version: >= 1.10 extra-source-files: README.md+ CHANGELOG.md executable nix-diff main-is: Main.hs
src/Main.hs view
@@ -28,7 +28,9 @@ import qualified Control.Monad.Reader import qualified Control.Monad.State import qualified Data.Attoparsec.Text+import qualified Data.Char as Char import qualified Data.Map+import qualified Data.List as List import qualified Data.Set import qualified Data.Text import qualified Data.Text.IO@@ -115,7 +117,7 @@ parserInfo :: ParserInfo Options parserInfo = Options.Applicative.info- parseOptions+ (Options.Applicative.helper <*> parseOptions) ( Options.Applicative.fullDesc <> Options.Applicative.header "Explain why two derivations differ" )@@ -237,35 +239,38 @@ -- | Color text background red redBackground :: Orientation -> TTY -> Text -> Text-redBackground Character IsTTY text = "\ESC[41m" <> text <> "\ESC[0m"-redBackground Word IsTTY text = "\ESC[41m" <> text <> " \ESC[0m"-redBackground Line IsTTY text = "\ESC[41m" <> text <> "\ESC[0m\n"-redBackground Character NotTTY text = "←" <> text <> "←"-redBackground Word NotTTY text = "←" <> text <> " ←"-redBackground Line NotTTY text = "- " <> text <> "\n"+redBackground Line IsTTY text = "\ESC[41m" <> prefix <> "\ESC[0m" <> suffix+ where+ (prefix, suffix) = Data.Text.break lineBoundary text+redBackground Word IsTTY text = "\ESC[41m" <> prefix <> "\ESC[0m" <> suffix+ where+ (prefix, suffix) = Data.Text.break wordBoundary text+redBackground Character IsTTY text = "\ESC[41m" <> text <> "\ESC[0m"+redBackground Line NotTTY text = "- " <> text+redBackground _ NotTTY text = "←" <> text <> "←" -- | Color text green green :: TTY -> Text -> Text-green IsTTY text = "\ESC[1;32m" <> text <> "\ESC[0m"+green IsTTY text = "\ESC[1;32m" <> text <> "\ESC[0m" green NotTTY text = text -- | Color text background green greenBackground :: Orientation -> TTY -> Text -> Text+greenBackground Line IsTTY text = "\ESC[42m" <> prefix <> "\ESC[0m" <> suffix+ where+ (prefix, suffix) = Data.Text.break lineBoundary text+greenBackground Word IsTTY text = "\ESC[42m" <> prefix <> "\ESC[0m" <> suffix+ where+ (prefix, suffix) = Data.Text.break wordBoundary text greenBackground Character IsTTY text = "\ESC[42m" <> text <> "\ESC[0m"-greenBackground Word IsTTY text = "\ESC[42m" <> text <> " \ESC[0m"-greenBackground Line IsTTY text = "\ESC[42m" <> text <> "\ESC[0m\n"-greenBackground Character NotTTY text = "→" <> text <> "→"-greenBackground Word NotTTY text = "→" <> text <> " →"-greenBackground Line NotTTY text = "+ " <> text <> "\n"+greenBackground Line NotTTY text = "+ " <> text+greenBackground _ NotTTY text = "→" <> text <> "→" -- | Color text grey grey :: Orientation -> TTY -> Text -> Text-grey Character IsTTY text = "\ESC[1;2m" <> text <> "\ESC[0m"-grey Word IsTTY text = "\ESC[1;2m" <> text <> " \ESC[0m"-grey Line IsTTY text = "\ESC[1;2m" <> text <> "\ESC[0m\n"-grey Character NotTTY text = text-grey Word NotTTY text = text <> " "-grey Line NotTTY text = " " <> text <> "\n"+grey _ IsTTY text = "\ESC[1;2m" <> text <> "\ESC[0m"+grey Line NotTTY text = " " <> text+grey _ NotTTY text = text -- | Format the left half of a diff minus :: TTY -> Text -> Text@@ -381,6 +386,40 @@ mapDiff f (Patience.New r) = Patience.New (f r) mapDiff f (Patience.Both l r) = Patience.Both (f l) (f r) +{-| Split `Text` into spans of `Text` that alternatively fail and satisfy the+ given predicate++ The first span (if present) does not satisfy the predicate (even if the+ span is empty)++ >>> decomposeOn (== 'b') "aabbaa"+ ["aa","bb","aa"]+ >>> decomposeOn (== 'b') "bbaa"+ ["","bb","aa"]+ >>> decomposeOn (== 'b') ""+ []+-}+decomposeOn :: (Char -> Bool) -> Text -> [Text]+decomposeOn predicate = unsatisfy+ where+ unsatisfy text+ | Data.Text.null text = []+ | otherwise = prefix : satisfy suffix+ where+ (prefix, suffix) = Data.Text.break predicate text++ satisfy text+ | Data.Text.null text = []+ | otherwise = prefix : unsatisfy suffix+ where+ (prefix, suffix) = Data.Text.span predicate text++lineBoundary :: Char -> Bool+lineBoundary = ('\n' ==)++wordBoundary :: Char -> Bool+wordBoundary = Char.isSpace+ -- | Diff two `Text` values diffText :: Text@@ -396,11 +435,19 @@ let leftString = Data.Text.unpack left let rightString = Data.Text.unpack right - let leftWords = Data.Text.splitOn " " left- let rightWords = Data.Text.splitOn " " right+ let decomposeWords = decomposeOn wordBoundary - let leftLines = Data.Text.lines left- let rightLines = Data.Text.lines right+ let decomposeLines text = loop (decomposeOn lineBoundary text)+ where+ -- Groups each newline character with the preceding line+ loop (x : y : zs) = (x <> y) : loop zs+ loop zs = zs++ let leftWords = decomposeWords left+ let rightWords = decomposeWords right++ let leftLines = decomposeLines left+ let rightLines = decomposeLines right let chunks = case orientation of