Coder Social home page Coder Social logo

walles / riff Goto Github PK

View Code? Open in Web Editor NEW
217.0 6.0 4.0 4.25 MB

A diff filter highlighting which line parts have changed

License: MIT License

Shell 5.44% Rust 89.84% Python 4.72%
riff refiner git-diff highlighting console-tool console-color diff

riff's Introduction

Riff, the Refining Diff

Riff is a wrapper around diff that highlights which parts of lines have changed.

Screenshot of riff in action

Much like git, Riff sends its output to a pager, trying these in order:

  1. Whatever is specified in the $PAGER environment variable
  2. moar because it is nice
  3. less because it is ubiquitous

Usage

git diff | riff

Or if you do...

git config --global pager.diff riff
git config --global pager.show riff
git config --global pager.log riff
git config --global interactive.diffFilter "riff --color=on"

... then all future git diff, git show and git log --patch output will be refined.

Or you can use riff as an alias for diff:

riff file1.txt file2.txt

Configuration

You can configure riff by setting the RIFF environment variable to one or more (space separated) command line options.

For example, set RIFF=--no-adds-only-special to disable adds-only special highlighting.

Installation

brew install riff
paru -S riffdiff
cargo install riffdiff

Manual Install

  1. Go here and download the correct binary for your platform

    • If no binary exists for your platform, please report it
  2. chmod a+x riff-*

  3. mv riff-* /usr/local/bin/riff

  4. Optionally followed by this to have riff highlight git output by default:

git config --global pager.diff riff
git config --global pager.show riff
git config --global pager.log riff
git config --global interactive.diffFilter "riff --color=on"

See Also

This VSCode extension for improved Git commit message editing is nice. Yes, I wrote it and I'm tooting my own horn here.

Good choice if you (like me!) are using VSCode for Git commit message editing.

More Features

riff can highlight conflict markers created by git:

Screenshot of riff highlighting conflict markers

riff highlighting a git merge commits highlighting

Screenshot of riff highlighting merge commits

Development

If you put example input and output in the testdata directory, then cargo test will verify that they match.

Invoke ci.sh to run the same thing as CI.

Invoke benchmark.py to get numbers for how fast your current source code is versus earlier releases.

Invoke git log -p | cargo run -- to demo highlighting.

Making a new release

Just invoke ./release.sh and follow instructions.

If you want to test the release script without actually releasing anything, do:

./release.sh --dry

TODO

Misc

  • Render ESC characters in the diff as Unicode โ›
  • --help: Only print installing-into-$PATH help if we aren't already being executed from inside of the $PATH
  • Do git show 57f27da and think about what rule we should use to get the REVERSE vs reversed() lines highlighted.
  • Add test for never changing the number of lines in the input, that messes up git add -p behavior.
  • Think about how to visualize an added line break together with some indentation on the following line.
  • Make sure we highlight the output of git show --stat properly
  • Make sure we can handle a git conflict resolution diff. File format is described at http://git-scm.com/docs/git-diff#_combined_diff_format.
  • Given three files on the command line, we should pass them and any options on to diff3 and highlight the result

TODO future

  • Detect moved blocks and use a number as a prefix for both the add and the remove part of the move. Highlight any changes just like for other changes.

DONE

  • Make a main program that can read input from stdin and print it to stdout.
  • Make the main program identify different kinds of lines by prefix and color them accordingly. Use the same color scheme as git.
  • Make the main program identify blocks of lines that have been replaced by another block of lines.
  • Make the Refiner not highlight anything if either old or new is empty
  • Use https://crates.io/crates/diffus to refine hunks
  • Build refined hunks and print them
  • Highlight ^diff, ^index, ^+++ and ^--- lines in bold white
  • Prefix all added / removed lines with the correct ANSI color code
  • Don't highlight the initial + / - on added / removed lines
  • Make sure we get the linefeeds right in diffs, try git show 28e074bd0fc246d1caa3738432806a94f6773185 with and without riff.
  • Visualize added line endings
  • Visualize removed line endings
  • Visualize removed linefeed at end of file properly
  • Visualize adding a missing linefeed at end of file properly
  • Visualize missing linefeed at end of file as part of the context properly
  • Refine ax->bx\nc properly
  • Strip all color from the input before handling it to enable users to set Git's pager.diff and pager.show variables to 'riff' without also needing to set color.diff=false.
  • If stdout is a terminal, pipe the output to a pager using the algorithm described under core.pager in git help config.
  • You can do git diff | riff and get reasonable output.
  • Do not highlight anything if there are "too many" differences between the sections. The point here is that we want to highlight changes, but if it's a replacement rather than a change then we don't want to highlight it.
  • Refine by word rather than by character
    • Test case git show 2ac5b06: Should highlight all of both some and one or.
  • Do some effort to prevent fork loops if people set $PAGER to riff
  • Add support for --help
  • Add support for --version
  • Print help and bail if stdin is a terminal
  • On exceptions, print the current version just like --version
  • On exceptions, print a link to the issue tracker
  • Add test case verifying that the Inspired by part of git show 77c8f77 -- bin/riff is highlighted as an upside down L.
  • Find out how the LCS algorithm scales and improve the heuristic for when not to call it.
  • Tune the upper bound on how large regions we should attempt to refine
  • Make a CI script
  • Set up CI calling the CI script
  • Document ci.sh's existence
  • Figure out cross compiling to Linux and macOS ARM (look into cross which uses Docker for cross compiling)
  • Make a release script
  • Document release.sh's existence
  • Verify that the Linux binary works
  • Document install instructions
  • Make a public release
  • Remedy release.sh FIXMEs
  • Add a trailing whitespace analysis pass to the Refiner
  • Let the Refiner highlight whitespace errors among the added lines in reverse red.
  • Highlight whitespace in added parts only
  • Add highlighting of non-leading tabs to the whitespace analysis
  • Profile and see if we can go faster
  • In ci.sh, add a test case verifying that our exception handler prints backtraces in release builds (should fail when stripping the release binary)
  • In ci.sh, add a test case verifying that our exception handler prints line numbers for the riff frames in the backtraces, in release builds. This should fail when stripping the release binary.
  • Require line numbers in backtraces in release builds
  • Make the Linux binary smaller
  • Put argv contents in crash report
  • Handle plain non-git diff files
  • Given two files on the command line, we should pass them on to diff and highlight the result.
  • Support riff -b path1 path2 to diff files ignoring whitespace
  • Bound how-much-to-highlight restriction by number of characters highlighted rather than by number of tokens highlighted
  • Get ourselves some kind of benchmark suite / example(s)
  • Do git show 5e0a1b2b13528f40299e78e3bfa590d9f96637af and scroll to the end. How should we visualize the reformatting of the No-newline-at-eof code?
  • Do git show 0f5dd84 and think about how to visualize one line changing to itself with a comma at the end plus a bunch of entirely new lines. Think of a constant array getting one or more extra members.
  • Do git show -b 77c8f77 and think about what rule we should use to highlight the leading spaces of the + refined and + page lines at the end of the file.

riff's People

Contributors

0x5c avatar cclauss avatar dependabot[bot] avatar just1602 avatar mend-bolt-for-github[bot] avatar walles avatar xeago avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

riff's Issues

Merge conflict highlight

Please add an option to pass only one file to riff, and if it contains merge conflicts, highlight the differences between the 2 chunks.

-b flag forces presence of <C1> <C2>

I'm not sure if this is expected behavior, but it seems strange to me if it is:

This works:

$ git diff dev | riff

But if I do the following, I get:

$ git diff dev | riff -b
error: the following required arguments were not provided:
  <C1>
  <C2>
(...)

-b is stated in --help as meaning "Ignore changes in amount of whitespace", I was assuming this should be possible for data passed on STDIN just as well as files on disk.

$ riff --version
riff 2.27.0

Underscores (_) as word parts

In the below diff, test_output should be treated as one word.

diff --git tools/bump-buildfarm-to-latest.sh tools/bump-buildfarm-to-latest.sh
index 591347e..1e68cdf 100755
--- tools/bump-buildfarm-to-latest.sh
+++ tools/bump-buildfarm-to-latest.sh
@@ -122,7 +122,7 @@ EOM

 after_rebase() {
     # Verify that upstream's test suite passes
-    bazelisk test -- //src/test/java/build/buildfarm:all
+    bazelisk test --test_output=errors -- //src/test/java/build/buildfarm:all

     # Push rebased changes back to Spotify's fork of upstream
     git push -u origin HEAD

Option to mark whole words

Currently a diff between

uintptr_t | CgreenValue

comes out as

    uintptr_t | CgreenValue

That doesn't show very well since it's not possible to color backgrounds here, but all except the 'r' is marked as different. It would be nice with an option to not be so detailed but instead regard whole words instead. For some definition of 'word'.

It is usually what you are interested in and much easier to read.

Love riff anyway!

Improve conflict highlighting

In the following conflict diff, the last section starting with ++// NOTE: When we search [...] should be colored as the context lines.

diff --cc m/search.go
index 5b67346,e5b580f..0000000
--- m/search.go
+++ m/search.go
@@@ -10,45 -6,9 +10,79 @@@ import 
  	"github.com/walles/moar/m/linenumbers"
  )
  
++<<<<<<< HEAD
 +func (p *Pager) scrollToSearchHits() {
 +	if p.searchPattern == nil {
 +		// This is not a search
 +		return
 +	}
 +
 +	lineNumber := p.scrollPosition.lineNumber(p)
 +	if lineNumber == nil {
 +		// No lines to search
 +		return
 +	}
 +
 +	firstHitPosition := p.findFirstHit(*lineNumber, nil, false)
 +	if firstHitPosition == nil && (*lineNumber != linenumbers.LineNumber{}) {
 +		// Try again from the top
 +		firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, lineNumber, false)
 +	}
 +	if firstHitPosition == nil {
 +		// No match, give up
 +		return
 +	}
 +
 +	if firstHitPosition.isVisible(p) {
 +		// Already on-screen, never mind
 +		return
 +	}
 +
 +	p.scrollPosition = *firstHitPosition
 +}
 +
 +// NOTE: When we search, we do that by looping over the *input lines*, not the
 +// screen lines. That's why startPosition is a LineNumber rather than a
 +// scrollPosition.
 +//
 +// The `beforePosition` parameter is exclusive, meaning that line will not be
 +// searched.
 +//
 +// For the actual searching, this method will call _findFirstHit() in parallel
 +// on multiple cores, to help large file search performance.
++||||||| parent of b835e9a (Fix the warnings)
++func (p *Pager) scrollToSearchHits() {
++	if p.searchPattern == nil {
++		// This is not a search
++		return
++	}
++
++	firstHitPosition := p.findFirstHit(*p.scrollPosition.lineNumber(p), nil, false)
++	if firstHitPosition == nil {
++		// Try again from the top
++		firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, p.scrollPosition.lineNumber(p), false)
++	}
++	if firstHitPosition == nil {
++		// No match, give up
++		return
++	}
++
++	if firstHitPosition.isVisible(p) {
++		// Already on-screen, never mind
++		return
++	}
++
++	p.scrollPosition = *firstHitPosition
++}
++
+ // NOTE: When we search, we do that by looping over the *input lines*, not
+ // the screen lines. That's why we're using a line number rather than a
+ // scrollPosition for searching.
++=======
++// NOTE: When we search, we do that by looping over the *input lines*, not
++// the screen lines. That's why we're using a line number rather than a
++// scrollPosition for searching.
++>>>>>>> b835e9a (Fix the warnings)
  //
  // FIXME: We should take startPosition.deltaScreenLines into account as well!
  func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, beforePosition *linenumbers.LineNumber, backwards bool) *scrollPosition {

Misaligned timestamps

Windows 7 x64 user here. I was looking for a speedy alternative to diff and came across riff (2.28.0). It is indeed way faster than busybox diff file1 file2 on my end. However, the output contains poorly aligned timestamps. Please, a) align timestamps and b) implement an option to omit them altogether (for example, to share diff via pastebins without exposing that kind of metadata).

$ riff original.hex patched.hex
--- original.hex        Thu Jan 25 23:37:19 2024
+++ patched.hex Thu Jan 25 23:38:40 2024
@@ -419964,7 +419964,7 @@
...

$ busybox diff original.hex patched.hex | riff
--- original.hex
+++ patched.hex
@@ -419964,7 +419964,7 @@

Originally posted by @sergeevabc in #47 (comment)

Highlight line expansion

In this case, the added line containing stream.write_all(text.as_bytes()) should have all the new chars highlighted, and the old line should have the removed .unwrap(); part highlighted.

diff --git a/src/main.rs b/src/main.rs
index 55a7c18..8826249 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -90,7 +91,15 @@ fn get_fixed_highlight(line: &str) -> &str {
 }

 fn print(stream: &mut BufWriter<&mut dyn Write>, text: &str) {
-    stream.write_all(text.as_bytes()).unwrap();
+    if let Err(error) = stream.write_all(text.as_bytes()) {
+        if error.kind() == ErrorKind::BrokenPipe {
+            // This is fine, somebody probably just quit their pager before it
+            // was done reading our output.
+            exit(0);
+        }
+
+        panic!("Error writing diff to pager: {:?}", error);
+    }
 }

 fn println(stream: &mut BufWriter<&mut dyn Write>, text: &str) {

Test installing gem on clean system

gem install riffdiff on a clean system makes it obvious that we're (at least) missing a dependency on slop.

Make sure it's possible to gem install riffdiff on a clean system.

riff tries to allocate a huge amount of memory when diffing large files

This happens in at least the following modes of operation when diffing large files:

  • diff -u file1 file2 | riff
  • riff file1 file2

This happens on the latest release but also happens in every version going back to 2.0. (built with cargo build --release)

$ riff --version
riff 2.22.0

$ riff omegat-sf.txt omegat-gh.txt
memory allocation of 308691186848 bytes failed
zsh: IOT instruction  riff omegat-sf.txt omegat-gh.txt

(that's 308GB)

riff omegat-sf.txt omegat-gh.txt strace (tarball, it's very large unpacked)
omegat-sf.txt
omegat-gh.txt

Highlight spaces between added consecutive words

Imagine this diff:

-Here is at least some candy
+Here is a lot of candy

Currently Riff will highlight all individual words changed; at, least, some, a, lot, of.

Instead, it would be better if Riff would also highlight the whitespace between the words, since I think is a better match for how a human would see this replacement.

At least this human would describe this change as "at least some was replaced by a lot of".

Bogus non-leading-tab warnings

Possibly in combination with our special rendering of adds-only.

Make sure to use tabs in the below example and it should repro the problem.

    if err != nil {
-       writeError(w, req, err)
+       writeError(r.logger, w, req, err)
        return
    }

"No newline at end of file" feature is dependent on system language being english

When the system language is not english, the output of diff -u will not contain the string \ No newline at end of file, but instead some translated text in the user's locale.

aaa

yo

bbb

yo

image
(the text is \ Pas de fin de ligne ร  la fin du fichier)

I would assume that the exact text used isn't part of the unified diff format, and at only the \ on col 1 of the line matters. It seems that gnu patch does indeed only care about the backslash, although I'm not sure if my reading of that code is correct.

- lines not highlighted if next to a line entirely of -----

$ riff --version
riff 2.22.0
diff --git a/docs/online/recovery-shell.rst b/docs/online/recovery-shell.rst
index 9dc42df..d3d8287 100755
--- a/docs/online/recovery-shell.rst
+++ b/docs/online/recovery-shell.rst
@@ -2,7 +2,7 @@ Recovery Shell
 ==============
 
 Common Commands
----------------
+===============
 
 *zfsbootmenu*

image

Request of windows binaries

Because

If no binary exists for your platform, please report it

and not everybody (from potential users) can build from Rust-sources by hand

Request: Option to disable paging

Sometimes I want to ensure the pager is not used, and can achieve that result by setting PAGER=cat, but I would prefer to use something like --no-pager.

Thanks for this project!

Ignore newline vs space

If a newline is replaced with a space character, or a space character is replaced with a newline, don't highlight this.

This is what happens when rewrapping text, and I think highlighting these changes doesn't help me understand what's going on.

Also consider what this would mean for indented text being rewrapped.

Ability to pass a diff/patch file as single argument

I often find myself wanting to have riff highlighting on a patch file. As of the current riff version, the only way to do that is to pipe the patch's content to riff. I however always fail to remember that and instead attempt to pass the patch's path as an argument.

It would be nice if riff would treat the case of only one non-flag argument as a signal to apply diff highlighting to the file's content, as if it had been passed as stdin.

Alternatively, this could be done with a flag like --(f)ile. This would still be more intuitive than cat <patch> | riff.

riff <file1> <file2>
# the diff of file1 and file2, highlighted; existing functionnality
riff <patchfile>
# the contents of patchfile, highlighted

Highlight renames

In the following example, we should highlight the --- Formula/riffdiff.rb and +++ Formula/riff.rb lines to indicate that riffdiff has been replaced by riff.

diff --git Formula/riffdiff.rb Formula/riff.rb
similarity index 95%
rename from Formula/riffdiff.rb
rename to Formula/riff.rb
index 9aa774e..a14fe98 100644
--- Formula/riffdiff.rb
+++ Formula/riff.rb
@@ -1,4 +1,4 @@
-class Riffdiff < Formula
+class Riff < Formula
   desc "Diff filter highlighting which line parts have changed"
   homepage "https://github.com/walles/riff"
   url "https://github.com/walles/riff/archive/2.23.3.tar.gz"

Request issues on slow performance

If refining takes too long, print stats afterwards and ask for people to report them.

We don't want riff to be slow, and if it is we should either fix the performance for that diff, or we should make riff just not highlight large enough input.

Also consider whether we can interrupt riff if it takes too long and just present input without highlighting in that case.

Broken highlighting

Highlighting this diff doesn't work, it comes out as all bold:

diff --cc bravo.py
index b8e3ee5,c7b9a04..0000000
--- a/bravo.py
+++ b/bravo.py
@@@ -82,11 -82,25 +82,25 @@@ class Bravo(object)

          return response

+     def proxy_elk_request(self, path, data):
+         received = requests.get(
+             '{}/{}'.format(LOGELASK_URL, '/'.join(path)),
+             data=data)
+ 
+         response = flask.make_response(received.content)
+         response.headers = dict(received.headers)
+         response.status_code = received.status_code
+ 
+         return response
+ 
 -    def proxy_route_path(self, proxy, path_array):
 +    def proxy_route_path(self, proxy, path):
          if proxy == 'teamcitylog':
 -            return self.stream_teamcitylog(path_array[0])
 +            return self.stream_teamcitylog(path)
          elif proxy == 'ghe':
 -            return self.proxy_ghe_request(path_array)
 +            return self.proxy_ghe_request(path)
+         elif proxy == 'elk':
 -            return self.proxy_elk_request(path_array,
++            return self.proxy_elk_request(path,
+                                           flask.request.get_data(as_text=True))
          else:
              raise ValueError('Unsupported proxy type: <{}>'.format(proxy))

Special highlighting for adds-only

--- /tmp/a.txt  2023-08-06 16:07:37.000000000 +0200
+++ /tmp/b.txt  2023-08-06 16:07:39.000000000 +0200
@@ -1,2 +1,2 @@
-Hello, my name is Johan
+Hello, my first name is Johan
 I like pie.

We should:

  • Lowlight the whole - line using Faint text
  • Color the + line like the I like pie. line
  • Highlight first in inverse bold green

This should better illustrate adds-only changes.

Unexpected highlight

The Problem

black is highlighted even though I think it shouldn't. Either explain this or fix it!

why-is-black-highlighted

The diff

--- /tmp/pirate/pirate-ipsum-before.txt	2020-12-31 00:11:15.000000000 +0100
+++ /tmp/pirate/pirate-ipsum-after.txt	2020-12-31 00:11:46.000000000 +0100
@@ -1,6 +1,7 @@
-Hornswaggle knave coffer rum Nelsons folly bilge water lugger. Fire in the hole black
-spot knave come about jury mast coxswain rutters. Keelhaul hail-shot Jack Ketch no prey,
-no pay gunwalls gaff haul wind. Ho fire in the hole Sail ho booty rum trysail hail-shot.
-Knave Letter of Marque barkadeer league mizzen strike colors spike. Jack Ketch spirits
-hail-shot long clothes walk the plank gabion warp. Poop deck holystone black spot tackle
-long boat loot run a shot across the bow.
+Hornswaggle knave coffer rum Nelsons folly bilge water lugger. Fire in the hole
+black spot knave come about jury mast coxswain rutters. Keelhaul hail-shot Jack
+Ketch no prey, no pay gunwalls gaff haul wind. Ho fire in the hole Sail ho booty
+rum trysail hail-shot. Knave Letter of Marque barkadeer league mizzen strike
+colors spike. Jack Ketch spirits hail-shot long clothes walk the plank gabion
+warp. Poop deck holystone black spot tackle long boat loot run a shot across the
+bow.

Quitting the pager while riff is writing crashes riff

Panic message: <PanicInfo {
    payload: Any,
    message: Some(
        called `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" },
    ),
    location: Location {
        file: "src/main.rs",
        line: 93,
        col: 39,
    },
}>

   0: backtrace::backtrace::trace
   1: backtrace::capture::Backtrace::new
   2: riff::main::{{closure}}
   3: std::panicking::rust_panic_with_hook
   4: std::panicking::begin_panic_handler::{{closure}}
   5: std::sys_common::backtrace::__rust_end_short_backtrace
   6: _rust_begin_unwind
   7: core::panicking::panic_fmt
   8: core::result::unwrap_failed
   9: riff::highlight_diff
  10: riff::try_pager
  11: riff::highlight_stream
  12: riff::main
  13: std::sys_common::backtrace::__rust_begin_short_backtrace
  14: std::rt::lang_start::{{closure}}
  15: std::rt::lang_start_internal
  16: _main

Riff version: 2.2-1-g1412b85

Command line arguments: Args { inner: ["riff", "hej/fast/", "hej/slow/"] }

Lowlight `--- /dev/null`

New files get headers saying --- /dev/null. In this case we should just lowlight that heading.

diff --git a/etc/db/004_table_gris.up.sql b/etc/db/004_table_gris.up.sql
new file mode 100644
index 0000000..ad5deba
--- /dev/null
+++ b/etc/db/004_table_gris.up.sql
@@ -0,0 +1,3 @@
+CREATE TABLE gris (
+  id uuid PRIMARY KEY
+);

Test failure when specifying a target triple

tests::test_testdata_examples fails since the binary path gains a new path component when a target is specified.

target/release/deps/riff-[hash] becomes
target/[triple]/release/deps/riff-[hash]

git_version breaks building from the github release tarballs

This line crashes builds when building riff from the release tarballs since they don't include the git information.

const GIT_VERSION: &str = git_version!();

The git_version documentation gives multiple options to fallback on the crate version specified in Cargo.toml. Since the crate version in release tarballs should be the same as the git tag, and that git tags are just references to commits, using that would not only not change anything for someone trying to checkout or diff the specific commit corresponding to a build, it would arguably be better since then now it's clearer a build from a release is not just a random unreleased commit from the repo HEAD.

Changing the line to this

const GIT_VERSION: &str = git_version!(cargo_prefix="");

allows the build and sets the version like so

$ riff --version
riff 0.1.0
[...]

This currently has 0.1.0, since that is the crate version declared in Cargo.toml. Of course, setting that properly would require changing the versioning scheme to 3 components instead of two, but that is also a requirement to publish crates.

In short, doing the modification to the git_version macro call and setting the crate version would allow all linux distros and others (#20) to package riff without friction and with proper version info.

Side note: If you decide to follow the same versioning/tagging scheme as moar, you'd want cargo_prefix="v" to match the tags.

Build for Homebrew

I am currently working on packaging riff for Homebrew-Core and since I am not familiar with Rust, I would need some assistance. Initial try with formula:

class Riffdiff < Formula
  desc "Diff filter highlighting which line parts have changed"
  homepage "https://github.com/walles/riff"
  url "https://github.com/walles/riff/archive/refs/tags/2.9.tar.gz"
  license "MIT"

  depends_on "rust" => :build

  def install
    system "cargo", "install", *std_cargo_args
  end
  ...

and brew install --verbose --build-from-source riffdiff:

   ...
   Compiling git-version-macro v0.3.4
   Compiling git-version v0.3.4
   Compiling riff v0.1.0 (/private/tmp/riffdiff-20210611-71464-14uq6on/riff-2.9)
error: git describe failed with status 128: fatal: not a git repository (or any of the parent directories): .git
  --> src/main.rs:62:27
   |
62 | const GIT_VERSION: &str = git_version!();
   |                           ^^^^^^^^^^^^^^
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

error: failed to compile `riff v0.1.0 (/private/tmp/riffdiff-20210611-71464-14uq6on/riff-2.9)`, intermediate artifacts can be found at `/private/tmp/riffdiff-20210611-71464-14uq6on/riff-2.9/target`

Caused by:
  could not compile `riff`
  ...

Second try with this install section:

  def install
    system "cargo", "build", "--release", *std_cargo_args
  end
...
/usr/bin/sandbox-exec -f /private/tmp/homebrew20210611-73336-orsj1b.sb nice ruby -W1 -- /usr/local/Homebrew/Library/Homebrew/build.rb /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/riffdiff.rb --verbose
tar --extract --no-same-owner --file /Users/admin/Library/Caches/Homebrew/downloads/b4cc31a19bf3e1cddff4bd171f148c6281f2f4ff6c202f77c37bab27964cf6bd--riff-2.9.tar.gz --directory /private/tmp/d20210611-73337-1dfmvfi
cp -pR /private/tmp/d20210611-73337-1dfmvfi/riff-2.9/. /private/tmp/riffdiff-20210611-73337-14teoag/riff-2.9
chmod -Rf +w /private/tmp/d20210611-73337-1dfmvfi
==> cargo build --release --locked --root /usr/local/Cellar/riffdiff/2.9 --path .
error: Found argument '--root' which wasn't expected, or isn't valid in this context

USAGE:
    cargo build --locked --release
...

Highlighting when middle line hasn't changed that much

In the following test case, the middle line should have &mut actual_result and file.reopen().unwrap() highlighted on the middle changed line, and nothing else.

I think highlighting fully changed lines has no value, that's why the first and last lines should not be highlighted.

git show af2c3de7840bf6307b34076eb4db782e3fcb0c42 src/main.rs | tail -13
@@ -442,9 +438,9 @@ mod tests {
             println!("Evaluating example file <{}>...", diff.to_str().unwrap());

             // Run highlighting on the file into a memory buffer
-            let mut actual_result: Vec<u8> = Vec::new();
-            highlight_diff(&mut fs::File::open(diff).unwrap(), &mut actual_result);
-            let actual_result = str::from_utf8(&actual_result).unwrap();
+            let file = tempfile::NamedTempFile::new().unwrap();
+            highlight_diff(&mut fs::File::open(diff).unwrap(), file.reopen().unwrap());
+            let actual_result = fs::read_to_string(file.path()).unwrap();

             // Load the corresponding .riff-output file into a string
             let basename = diff.file_stem().unwrap().to_str().unwrap();

[feature request] side-by-side mode

I'm not sure if this would fit into the philosophy of this application, but if so, I would love to see the option to compare differences side by side: on the left what was removed, and on the right what was added.

Panic while running `git diff`

I set riff as pager for git diff with git config --global pager.diff riff. (and for all the other git config options, too).

Installation of riff

I had it installed via AUR but installed it manually to get the debuginfo for the backtrace. So I did

git clone https://github.com/walles/riff.git
cd riff
cargo install --path .

riff --version: riff 2.25.2-11-gfffc7d6

Reproduction

The crashes happen in my git repo of my dotfiles.

git clone https://github.com/maaxxs/dotfiles.git
cd dotfiles
git diff 2>riff.err

panics

In my dotfiles repo I get the following crashes when running git diff.

Also note, when I run this, I only see the errors flashing by and then it shows the output of git diff and it looks like it's colored correctly.

riff.err
-v-v-v----------- RIFF CRASHED ---------------v-v-v-

Panic message: <PanicInfo {
    payload: Any { .. },
    message: Some(
        called `Option::unwrap()` on a `None` value,
    ),
    location: Location {
        file: "src/refiner.rs",
        line: 33,
        col: 74,
    },
    can_unwind: true,
}>

   0: riff::panic_handler
             at /home/user/dev/riff/src/main.rs:184:23
   1: riff::main::{{closure}}
             at /home/user/dev/riff/src/main.rs:317:9
   2: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1999:9
      std::panicking::rust_panic_with_hook
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:709:13
   3: std::panicking::begin_panic_handler::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:595:13
   4: std::sys_common::backtrace::__rust_end_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:151:18
   5: rust_begin_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
   6: core::panicking::panic_fmt
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
   7: core::panicking::panic
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:117:5
   8: core::option::Option<T>::unwrap
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/option.rs:935:21
   9: riff::refiner::format_simple
             at /home/user/dev/riff/src/refiner.rs:33:37
  10: riff::refiner::format
             at /home/user/dev/riff/src/refiner.rs:78:16
  11: riff::line_collector::StringFuture::from_oldnew::{{closure}}
             at /home/user/dev/riff/src/line_collector.rs:105:25
  12: <F as threadpool::FnBox>::call_box
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:95:9
  13: threadpool::spawn_in_pool::{{closure}}
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:769:17
  14: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:135:18
  15: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:529:17
  16: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panic/unwind_safe.rs:271:9
  17: std::panicking::try::do_call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:500:40
  18: __rust_try
  19: std::panicking::try
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:464:19
  20: std::panic::catch_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panic.rs:142:14
      std::thread::Builder::spawn_unchecked_::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:528:30
  21: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/ops/function.rs:250:5
  22: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      std::sys::unix::thread::Thread::new::thread_start
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys/unix/thread.rs:108:17
  23: <unknown>
  24: <unknown>

Riff version: 2.25.2-11-gfffc7d6

Command line arguments: Args { inner: ["/home/user/.cargo/bin/riff"] }

-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-


Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <[email protected]>



-v-v-v----------- RIFF CRASHED ---------------v-v-v-

Panic message: <PanicInfo {
    payload: Any { .. },
    message: Some(
        called `Result::unwrap()` on an `Err` value: PoisonError { .. },
    ),
    location: Location {
        file: "src/refiner.rs",
        line: 181,
        col: 79,
    },
    can_unwind: true,
}>



-v-v-v----------- RIFF CRASHED ---------------v-v-v-

Panic message: <PanicInfo {
    payload: Any { .. },
    message: Some(
        called `Result::unwrap()` on an `Err` value: RecvError,
    ),
    location: Location {
        file: "src/line_collector.rs",
        line: 129,
        col: 43,
    },
    can_unwind: true,
}>

   0: riff::panic_handler
             at /home/user/dev/riff/src/main.rs:184:23
   1: riff::main::{{closure}}
             at /home/user/dev/riff/src/main.rs:317:9
   2: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1999:9
      std::panicking::rust_panic_with_hook
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:709:13
   3: std::panicking::begin_panic_handler::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:597:13
   4: std::sys_common::backtrace::__rust_end_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:151:18
   5: rust_begin_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
   6: core::panicking::panic_fmt
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
   7: core::result::unwrap_failed
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1651:5
   8: core::result::Result<T,E>::unwrap
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1076:23
   9: riff::refiner::to_lines
             at /home/user/dev/riff/src/refiner.rs:181:43
  10: riff::refiner::format
             at /home/user/dev/riff/src/refiner.rs:98:12
  11: riff::line_collector::StringFuture::from_oldnew::{{closure}}
             at /home/user/dev/riff/src/line_collector.rs:105:25
  12: <F as threadpool::FnBox>::call_box
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:95:9
  13: threadpool::spawn_in_pool::{{closure}}
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:769:17
  14: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:135:18
  15: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:529:17
  16: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panic/unwind_safe.rs:271:9
  17: std::panicking::try::do_call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:500:40
  18: __rust_try
  19: std::panicking::try
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:464:19
  20: std::panic::catch_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panic.rs:142:14
      std::thread::Builder::spawn_unchecked_::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:528:30
  21: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/ops/function.rs:250:5
  22: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      std::sys::unix::thread::Thread::new::thread_start
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys/unix/thread.rs:108:17
  23: <unknown>
  24: <unknown>

Riff version: 2.25.2-11-gfffc7d6

Command line arguments: Args { inner: ["/home/user/.cargo/bin/riff"] }

-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-


Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <[email protected]>



-v-v-v----------- RIFF CRASHED ---------------v-v-v-

Panic message: <PanicInfo {
    payload: Any { .. },
    message: Some(
        called `Result::unwrap()` on an `Err` value: PoisonError { .. },
    ),
    location: Location {
        file: "src/refiner.rs",
        line: 32,
        col: 79,
    },
    can_unwind: true,
}>

   0: riff::panic_handler
             at /home/user/dev/riff/src/main.rs:184:23
   1: riff::main::{{closure}}
             at /home/user/dev/riff/src/main.rs:317:9
   2: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1999:9
      std::panicking::rust_panic_with_hook
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:709:13
   3: std::panicking::begin_panic_handler::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:597:13
   4: std::sys_common::backtrace::__rust_end_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:151:18
   5: rust_begin_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
   6: core::panicking::panic_fmt
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
   7: core::result::unwrap_failed
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1651:5
   8: core::result::Result<T,E>::unwrap
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1076:23
   9: riff::line_collector::StringFuture::get
             at /home/user/dev/riff/src/line_collector.rs:129:27
  10: riff::line_collector::StringFuture::is_empty
             at /home/user/dev/riff/src/line_collector.rs:122:16
  11: riff::line_collector::LineCollector::new::{{closure}}
             at /home/user/dev/riff/src/line_collector.rs:210:28
  12: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:135:18
  13: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:529:17
  14: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panic/unwind_safe.rs:271:9
  15: std::panicking::try::do_call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:500:40
  16: __rust_try
  17: std::panicking::try
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:464:19
  18: std::panic::catch_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panic.rs:142:14
      std::thread::Builder::spawn_unchecked_::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:528:30
  19: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/ops/function.rs:250:5
  20: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      std::sys::unix::thread::Thread::new::thread_start
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys/unix/thread.rs:108:17
  21: <unknown>
  22: <unknown>

   0: riff::panic_handler
             at /home/user/dev/riff/src/main.rs:184:23
   1: riff::main::{{closure}}
             at /home/user/dev/riff/src/main.rs:317:9
   2: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1999:9
      std::panicking::rust_panic_with_hook
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:709:13
   3: std::panicking::begin_panic_handler::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:597:13
   4: std::sys_common::backtrace::__rust_end_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:151:18
   5: rust_begin_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
   6: core::panicking::panic_fmt
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
   7: core::result::unwrap_failed
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1651:5
   8: core::result::Result<T,E>::unwrap
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1076:23
   9: riff::refiner::format_simple
             at /home/user/dev/riff/src/refiner.rs:32:43
  10: riff::refiner::format
             at /home/user/dev/riff/src/refiner.rs:78:16
  11: riff::line_collector::StringFuture::from_oldnew::{{closure}}
             at /home/user/dev/riff/src/line_collector.rs:105:25
  12: <F as threadpool::FnBox>::call_box
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:95:9
  13: threadpool::spawn_in_pool::{{closure}}
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:769:17
  14: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:135:18
  15: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:529:17
  16: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panic/unwind_safe.rs:271:9
  17: std::panicking::try::do_call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:500:40
  18: __rust_try
  19: std::panicking::try
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:464:19
  20: std::panic::catch_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panic.rs:142:14
      std::thread::Builder::spawn_unchecked_::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:528:30
  21: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/ops/function.rs:250:5
  22: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      std::sys::unix::thread::Thread::new::thread_start
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys/unix/thread.rs:108:17
  23: <unknown>
  24: <unknown>

Riff version: 2.25.2-11-gfffc7d6

Command line arguments: Args { inner: ["/home/user/.cargo/bin/riff"] }

-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-


Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <[email protected]>

Riff version: 2.25.2-11-gfffc7d6

Command line arguments: Args { inner: ["/home/user/.cargo/bin/riff"] }

-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-


Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <[email protected]>



-v-v-v----------- RIFF CRASHED ---------------v-v-v-

Panic message: <PanicInfo {
    payload: Any { .. },
    message: Some(
        called `Result::unwrap()` on an `Err` value: PoisonError { .. },
    ),
    location: Location {
        file: "src/refiner.rs",
        line: 32,
        col: 79,
    },
    can_unwind: true,
}>

   0: riff::panic_handler
             at /home/user/dev/riff/src/main.rs:184:23
   1: riff::main::{{closure}}
             at /home/user/dev/riff/src/main.rs:317:9
   2: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1999:9
      std::panicking::rust_panic_with_hook
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:709:13
   3: std::panicking::begin_panic_handler::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:597:13
   4: std::sys_common::backtrace::__rust_end_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:151:18
   5: rust_begin_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
   6: core::panicking::panic_fmt
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
   7: core::result::unwrap_failed
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1651:5
   8: core::result::Result<T,E>::unwrap
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/result.rs:1076:23
   9: riff::refiner::format_simple
             at /home/user/dev/riff/src/refiner.rs:32:43
  10: riff::refiner::format
             at /home/user/dev/riff/src/refiner.rs:78:16
  11: riff::line_collector::StringFuture::from_oldnew::{{closure}}
             at /home/user/dev/riff/src/line_collector.rs:105:25
  12: <F as threadpool::FnBox>::call_box
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:95:9
  13: threadpool::spawn_in_pool::{{closure}}
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/threadpool-1.8.1/src/lib.rs:769:17
  14: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys_common/backtrace.rs:135:18
  15: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:529:17
  16: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panic/unwind_safe.rs:271:9
  17: std::panicking::try::do_call
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:500:40
  18: __rust_try
  19: std::panicking::try
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:464:19
  20: std::panic::catch_unwind
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panic.rs:142:14
      std::thread::Builder::spawn_unchecked_::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/thread/mod.rs:528:30
  21: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/ops/function.rs:250:5
  22: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/boxed.rs:1985:9
      std::sys::unix::thread::Thread::new::thread_start
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/sys/unix/thread.rs:108:17
  23: <unknown>
  24: <unknown>

Riff version: 2.25.2-11-gfffc7d6

Command line arguments: Args { inner: ["/home/user/.cargo/bin/riff"] }

-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-


Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <[email protected]>

crash on git diff

when doing git diff during a rebase with unmerged conflicts, I was able to crash riff. It reproduces outside of git if copying the offending diff to a file and rendering that.

panic message:

-v-v-v----------- RIFF CRASHED ---------------v-v-v-

Panic message: <PanicInfo {
    payload: Any { .. },
    message: Some(
        assertion failed: line.starts_with('\\'),
    ),
    location: Location {
        file: "src/hunk_highlighter.rs",
        line: 158,
        col: 9,
    },
    can_unwind: true,
    force_no_backtrace: false,
}>

   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: <unknown>
  10: <unknown>
  11: <unknown>
  12: <unknown>
  13: <unknown>
  14: <unknown>
  15: <unknown>
  16: <unknown>
  17: __libc_start_call_main
             at ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
  18: __libc_start_main_impl
             at ./csu/../csu/libc-start.c:360:3
  19: <unknown>

Riff version: 3.1.0

Command line arguments: Args { inner: ["riff", "-f", "/tmp/bad.diff"] }

-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-


Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <[email protected]>

ERROR at end of input: Still expecting more lines, but got EOF: [0, 3, 0]

diff that caused the crash:

diff --cc ansible/roles/zfsbootmenu/tasks/main.yaml
index 73fa864,08648fa..0000000
--- a/ansible/roles/zfsbootmenu/tasks/main.yaml
+++ b/ansible/roles/zfsbootmenu/tasks/main.yaml
@@@ -6,6 -6,60 +6,60 @@@
        - zfsbootmenu
      state: present
  
++<<<<<<< HEAD
++=======
+ - name: Create ESP mdadm config
+   template:
+     src: mdadm.conf.j2
+     dest: /etc/mdadm.conf
+     owner: root
+     group: root
+     mode: 0644
+   when: esp_mdadm_array is defined
+ 
+ - name: Install dropbear
+   xbps:
+     pkg:
+       - dropbear
+       - mkinitcpio-dropbear
+     state: present
+ 
+ - name: Create dropbear directory
+   file:
+     path: /etc/dropbear
+     owner: root
+     group: root
+     mode: 0755
+     state: directory
+ 
+ - name: Create dropbear keys
+   command:
+     cmd: /usr/bin/dropbearkey -t {{ item }} -f /etc/dropbear/dropbear_{{ item }}_host_key
+     creates: /etc/dropbear/dropbear_{{ item }}_host_key
+   loop:
+     - rsa
+     - ecdsa
+     - ed25519
+ 
+ - name: Create dropbear authorised keys
+   template:
+     src: authorized_keys.j2
+     dest: /etc/dropbear/root_key
+     owner: root
+     group: root
+     mode: 0644
+     lstrip_blocks: true
+ 
+ - name: Create dropbear config
+   template:
+     src: dropbear.conf.j2
+     dest: /etc/dropbear/dropbear.conf
+     owner: root
+     group: root
+     mode: 0644
+     lstrip_blocks: true
+ 
++>>>>>>> 8eec118 (fixup! ansible/roles/zfsbootmenu: add role)
  - name: Create zfsbootmenu config
    template:
      src: config.yaml.j2
* Unmerged path ansible/host_vars/foo.yaml

Push tags to Github

There are no tags in this Github repo, which makes the unit tests fail...

Fix!

Remove-ending-newline highlighing with added lines

This diff should have a red removed-newline marker at the end of the last addition line:

--- /tmp/before.txt	2023-04-17 07:11:37.000000000 +0200
+++ /tmp/after.txt	2023-04-17 07:13:14.000000000 +0200
@@ -1 +1,3 @@
 Hello
+
+No trailing newline
\ No newline at end of file

unable to compare output of commands with bash/zsh redirection

in bash and zsh (and maybe other shells), the <() operator redirects a command's output as a file descriptor using a FIFO. This can be used with gnu diff to compare the outputs of commands (as shown below), but it doesn't work with riff. Would it be possible to add support for this?

$ diff <(cmd1) <(cmd2)
# works
$ riff <(cmd1) <(cmd2)
Can only compare file to file or directory to directory, not like this:
  Not file not dir: /proc/self/fd/11
  Not file not dir: /proc/self/fd/12

Riff Crashed during `git stash show -p`

------------ RIFF CRASHED -------------------
0: backtrace::backtrace::trace
1: backtrace::capture::Backtrace::new
2: riff::main::{{closure}}
3: std::panicking::rust_panic_with_hook
4: std::panicking::begin_panic_handler::{{closure}}
5: std::sys_common::backtrace::__rust_end_short_backtrace
6: _rust_begin_unwind
7: core::panicking::panic_fmt
8: core::result::unwrap_failed
9: riff::highlight_diff
10: riff::try_pager
11: riff::main
12: std::sys_common::backtrace::__rust_begin_short_backtrace
13: std::rt::lang_start::{{closure}}
14: std::rt::lang_start_internal
15: _main

Riff version: 2.0

Diff file not highlighted

This file doesn't get properly highlighted by riff, neither with line colors nor with reverse video for the actual changes:

--- srvadmin~7.1.0-1/openmanage/oma/ini/omcli.ini       2012-08-03 08:13:20.000000000 -0600
+++ /etc/opt/dell/srvadmin/openmanage/oma/ini/omcli.ini 2012-10-29 02:46:45.993168082 -0600
@@ -63,8 +63,8 @@
 recovery=sngl,cdll,sysclp
 shutdown=sngl,cdll,sysclp
 thrmshutdown=sngl,cdll,sysclp
-summary=mult,oma,common,Summary.xsl,cdll,sysclp,cdll,chaclp,cdll,ssclp
-version=mult,oma,cli,Summary.xsl,cdll,sysclp,cdll,ssclp
+summary=mult,oma,common,Summary.xsl,cdll,sysclp,cdll,chaclp
+version=mult,oma,cli,Summary.xsl,cdll,sysclp
 validate=sngl,cdll,sysclp
 progress=sngl,cdll,sysclp
 [omreport chassis]
@@ -146,8 +146,8 @@
 recovery=sngl,cdll,sysclp
 shutdown=sngl,cdll,sysclp
 thrmshutdown=sngl,cdll,sysclp
-summary=mult,oma,common,Summary.xsl,cdll,sysclp,cdll,chaclp,cdll,ssclp
-version=mult,oma,cli,Summary.xsl,cdll,sysclp,cdll,ssclp
+summary=mult,oma,common,Summary.xsl,cdll,sysclp,cdll,chaclp
+version=mult,oma,cli,Summary.xsl,cdll,sysclp
 validate=sngl,cdll,sysclp
 progress=sngl,cdll,sysclp
 [omreport mainsystem]

combined git diff highlighting

I'm still thinking about how best to highlight this, but I wanted to make sure I didn't forget to make the issue. I think to do more than simple highlighting it may require more than 16 colours for something coherent (see #47 (comment))

see also discussion in #56

diff --cc file
index 33448ee1e84,aac74526155..00000000000
--- a/file
+++ b/file
@@@ -527,9 -528,14 +528,14 @@@
- static void describe(char *arg)
 -static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
  {
+ 	struct commit *cmit;
 +	unsigned char sha1[20];

Leak of control characters

Hiya!

While using riff-2.0/riff-2.2 as a pager, I've encountered a diff that causes it to leak control characters. Piping the raw diff into riff reproduces with the same results. Using Kitty as terminal emulator. Annoyingly this does not occur on Apple Terminal.


Raw diff: git diff | cat

diff --git a/app.yaml b/app.yaml
index 2da370d..f7f39fc 100644
--- a/app.yaml
+++ b/app.yaml
@@ -11,10 +11,8 @@ handlers:
 -   url: /api/.*
     script: auto
 -   url: /(.*)
-    static_files: ui/dist/\1
-    upload: ui/dist/(.*)
-error_handlers:
--   file: ui/dist/default_error.html
+    static_files: ui/build/\1
+    upload: ui/build/(.*)
 env_variables:
     PGUSER: postgres
     CLOUD_SQL_CONNECTION_NAME: /cloudsql/animated-sniffle:europe-west1:pg-animated-sniffle

Diff as textual render: git diff

diff --git a/app.yaml b/app.yaml
index 2da370d..f7f39fc 100644
--- a/app.yaml
+++ b/app.yaml
@@ -11,10 +11,8 @@ handlers:
 -   url: /api/.*
     script: auto
 -   url: /(.*)
-    static_files: ui/dist/\1
-    upload: ui/dist/(.*)<E2><8F><8E>
-error_handlers:<E2><8F><8E>
--   file: ui/dist/default_error.html
+    static_files: ui/build/\1
+    upload: ui/build/(.*)
 env_variables:
     PGUSER: postgres
     CLOUD_SQL_CONNECTION_NAME: /cloudsql/animated-sniffle:europe-west1:pg-animated-sniffle

Diff as graphical render:
image

Highlight prepended lines

In the below diff, we should highlight the added part , env=buildenv on the subprocess.run() line.

diff --git benchmark.py benchmark.py
index a191ee0..d99c8a8 100755
--- benchmark.py
+++ benchmark.py
@@ -76,7 +76,9 @@ def gather_binaries():
     # Build the current version
     print()
     print("Building current sources...")
-    subprocess.run(["cargo", "build", "--release"], check=True)
+    buildenv = os.environ.copy()
+    buildenv["RUSTFLAGS"] = "-Awarnings"
+    subprocess.run(["cargo", "build", "--release"], check=True, env=buildenv)
     shutil.copy("target/release/riff", os.path.join(BINDIR, "riff-current"))

Related to #21.

Installation via cargo

Would be possible for you, to put riff to crates.io and thank to this install riff with cargo install riff?

Don't highlight complete lines

Highlighting a full line feels like it misses the point of highlighting, then it could be better to not highlight it at all.

Removes diff line

If you pass this through riff it will filter out the -THROTTLE_SECONDS line.

diff --git a/mailstash/mailstash.py b/mailstash/mailstash.py
index a1d5838..4b086f4 100755
--- a/mailstash/mailstash.py
+++ b/mailstash/mailstash.py
@@ -35,7 +35,9 @@ WARNING_KEYWORDS = ["WARN", "Warn", "warning"]

 # At most one message every THROTTLE_SECONDS will be sent to Elasticsearch,
 # set to None to disable
-THROTTLE_SECONDS = 51
+#
+# Monkey
+THROTTLE_SECONDS = None

 # We'll just truncate e-mail bodies longer than this
 MAX_LINES = 400

Readability issues in recently added features, +config file?

Some of the new highlight features in recent-ish versions are creating readability issues for me (details further down). I see the value in those features, so I wouldn't advise removing them. I think the best approach is to make them configurable, either through enabled/disabled switches, or through the ability to specify the style to use for each "token" (for lack of a better word). This last approach would also double as a way to customise colours for colourblindness accessibility and personal preference. Configuration could be done using a config file and/or environment variables, the former being more user-friendly.

Renamed files highlighting

I like this way of highlighting renames, but dark grey on red/green is very hard to read. This one seems to simply be a bug; the foreground black being turned into "bright black" by the bright/bold modifier on the whole filename. Should be fixable by setting the foreground of the highlight area to no-bold. I'll try to make a fix for that one.
image

"Only additions" highlight

With this highlight, it becomes very hard to read the before line (especially with partial red-green colourblindness), which for me means that I can't easily parse the diff since I need both the + and - lines.
image

Added/removed files lowlighting

Similar to the problem with "only additions" highlight, this one makes it harder for me to process that a file has been deleted/added since the lack of the other line removes the comparison point. It's slightly less pronounced than "only additions" because of the colour, but still causes difficulty parsing.
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.