diff --git a/.github/workflows/awesomebot.yml b/.github/workflows/awesomebot.yml new file mode 100644 index 0000000..f94abc4 --- /dev/null +++ b/.github/workflows/awesomebot.yml @@ -0,0 +1,23 @@ +--- +name: Check links in README + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + # Full git history is needed to get a proper list of changed files + # within `mega-linter` + fetch-depth: 0 + - uses: docker://dkhamsing/awesome_bot:latest + with: + args: /github/workspace/README.md --allow-ssl --allow 202,500,501,502,503,504,509,521 --allow-dupe --allow-redirect --request-delay 1 diff --git a/README.md b/README.md index 30ae547..50f9d9d 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,22 @@ -# diff-so-fancy [![Circle CI build](https://circleci.com/gh/so-fancy/diff-so-fancy.svg?style=shield)](https://circleci.com/gh/so-fancy/diff-so-fancy) [![TravisCI build](https://travis-ci.org/so-fancy/diff-so-fancy.svg?branch=master)](https://travis-ci.org/so-fancy/diff-so-fancy) [![AppVeyor build](https://ci.appveyor.com/api/projects/status/github/so-fancy/diff-so-fancy?branch=master&svg=true)](https://ci.appveyor.com/project/stevemao/diff-so-fancy/branch/master) +# 🎩 diff-so-fancy [![Circle CI build](https://circleci.com/gh/so-fancy/diff-so-fancy.svg?style=shield)](https://circleci.com/gh/so-fancy/diff-so-fancy) [![AppVeyor build](https://ci.appveyor.com/api/projects/status/github/so-fancy/diff-so-fancy?branch=master&svg=true)](https://ci.appveyor.com/project/stevemao/diff-so-fancy/branch/master) `diff-so-fancy` strives to make your diffs **human** readable instead of machine readable. This helps improve code quality and helps you spot defects faster. -## Screenshot +## 🖼️ Screenshot Vanilla `git diff` vs `git` and `diff-so-fancy` ![diff-highlight vs diff-so-fancy](diff-so-fancy.png) -## Install +## 📦 Install -Installation is as simple as cloning this repo and then putting the `diff-so-fancy` script in to your `$PATH`. The `lib/` directory will need to be kept relative to the core script. +Simply copy the `diff-so-fancy` script from the latest release into your `$PATH` and you're done. Alternately to test development features you can clone this repo and then put the `diff-so-fancy` script (symlink will work) into your `$PATH`. The `lib/` directory will need to be kept relative to the core script. -If you are using a ZSH framework like [zgenom](https://github.com/jandamm/zgenom) or [oh-my-zsh](https://ohmyz.sh), refer to [ZSH framework install](zsh-frameworks.md) for detailed installation instructions. +`diff-so-fancy` is also available from the [NPM registry](https://www.npmjs.com/package/diff-so-fancy), [brew](https://formulae.brew.sh/formula/diff-so-fancy), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch extra repo](https://archlinux.org/packages/extra/any/diff-so-fancy/), and as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian). -`diff-so-fancy` is also available from the [NPM registry](https://www.npmjs.com/package/diff-so-fancy), [brew](https://formulae.brew.sh/formula/diff-so-fancy), as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch extra repo](https://archlinux.org/packages/extra/any/diff-so-fancy/), and as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian). +Issues relating to packaging ("installation does not work", "version is out of date", etc.) should be directed to those packages' repositories/issue trackers where applicable. -Issues relating to packaging ('installation does not work', 'version is out of date', etc.) should be directed to those packages' own repositories/issue trackers where applicable. - -**Note:** Windows users may need to install [MinGW](https://sourceforge.net/projects/mingw/files/) or the [Windows subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10). - -## Usage +## ✨ Usage ### With git @@ -31,28 +27,7 @@ git config --global core.pager "diff-so-fancy | less --tabs=4 -RF" git config --global interactive.diffFilter "diff-so-fancy --patch" ``` -### Improved colors for the highlighted bits - -The default Git colors are not optimal. The colors used for the screenshot above were: - -```shell -git config --global color.ui true - -git config --global color.diff-highlight.oldNormal "red bold" -git config --global color.diff-highlight.oldHighlight "red bold 52" -git config --global color.diff-highlight.newNormal "green bold" -git config --global color.diff-highlight.newHighlight "green bold 22" - -git config --global color.diff.meta "11" -git config --global color.diff.frag "magenta bold" -git config --global color.diff.func "146 bold" -git config --global color.diff.commit "yellow bold" -git config --global color.diff.old "red bold" -git config --global color.diff.new "green bold" -git config --global color.diff.whitespace "red reverse" -``` - -### With diff +### Manually with diff Use `-u` with `diff` for unified output, and pipe the output to `diff-so-fancy`: @@ -69,7 +44,7 @@ diff -r -u folder_a folder_b | diff-so-fancy ```shell diff --recursive -u folder_a folder_b | diff-so-fancy ``` -## Options +## ⚒️ Options ### markEmptyLines @@ -108,10 +83,10 @@ git config --bool --global diff-so-fancy.useUnicodeRuler false By default, the separator for the file header spans the full width of the terminal. Use this setting to set the width of the file header manually. ```shell -git config --global diff-so-fancy.rulerWidth 47 # git log's commit header width +git config --global diff-so-fancy.rulerWidth 80 ``` -## The diff-so-fancy team +## 👨 The diff-so-fancy team | Person | Role | | --------------------- | ---------------- | @@ -121,7 +96,7 @@ git config --global diff-so-fancy.rulerWidth 47 # git log's commit header wid | @AOS | Debian packager | | @Stevemao/@Paul Irish | NPM release team | -## Contributing +## 🧬 Contributing Pull requests are quite welcome, and should target the [`next` branch](https://github.com/so-fancy/diff-so-fancy/tree/next). We are also looking for any feedback or ideas on how to make `diff-so-fancy` even *fancier*. @@ -132,10 +107,11 @@ Pull requests are quite welcome, and should target the [`next` branch](https://g * [Hacking and Testing](hacking-and-testing.md) * [History](history.md) -## Alternatives +## 🔃 Alternatives -* https://github.com/dandavison/delta +* [Delta](https://github.com/dandavison/delta) +* [Lazygit](https://github.com/jesseduffield/lazygit) with diff-so-fancy [integration](https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md#diff-so-fancy) -## License +## 🏛️ License MIT diff --git a/diff-so-fancy b/diff-so-fancy index da5277a..d952098 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -47,6 +47,10 @@ my $columns_to_remove = 0; my $is_mercurial = 0; my $color_forced = 0; # Has the color been forced on/off +if ($args->{rulerWidth}) { + $ruler_width = int($args->{rulerWidth}); +} + # We try and be smart about whether we need to do line coloring, but # this is an option to force it on/off if ($args->{color_on}) { @@ -106,13 +110,13 @@ my @lines; local $DiffHighlight::line_cb = sub { push(@lines,@_); - my $last_line = $lines[-1]; + my $prev_line = $lines[-1]; # Buffer X lines before we try and output anything # Also make sure we're sending enough data to d-s-f to do it's magic. # Certain things require a look-ahead line or two to function so # we make sure we don't break on those sections prematurely - if (@lines > 24 && ($last_line !~ /^${ansi_color_regex}(---|index|old mode|similarity index|rename (from|to))/)) { + if (@lines > 24 && ($prev_line !~ /^${ansi_color_regex}(---|index|old mode|similarity index|rename (from|to))/)) { do_dsf_stuff(\@lines); @lines = (); } @@ -823,18 +827,21 @@ sub set_defaults { # Borrowed from: https://www.perturb.org/display/1167_Perl_ANSI_colors.html # String format: '115', '165_bold', '10_on_140', 'reset', 'on_173', 'red', 'white_on_blue' sub color { - my $str = shift(); + my ($str, $txt) = @_; + + # If we're NOT connected to a an interactive terminal don't do color + #if (-t STDOUT == 0) { return ''; } # No string sent in, so we just reset if (!length($str) || $str eq 'reset') { return "\e[0m"; } # Some predefined colors - my %color_map = qw(red 160 blue 21 green 34 yellow 226 orange 214 purple 93 white 15 black 0); + my %color_map = qw(red 160 blue 27 green 34 yellow 226 orange 214 purple 93 white 15 black 0); $str =~ s|([A-Za-z]+)|$color_map{$1} // $1|eg; # Get foreground/background and any commands - my ($fc,$cmd) = $str =~ /(\d+)?_?(\w+)?/g; - my ($bc) = $str =~ /on_?(\d+)/g; + my ($fc,$cmd) = $str =~ /^(\d{1,3})?_?(\w+)?$/g; + my ($bc) = $str =~ /on_(\d{1,3})$/g; # Some predefined commands my %cmd_map = qw(bold 1 italic 3 underline 4 blink 5 inverse 7); @@ -844,46 +851,45 @@ sub color { if ($cmd_num) { $ret .= "\e[${cmd_num}m"; } if (defined($fc)) { $ret .= "\e[38;5;${fc}m"; } if (defined($bc)) { $ret .= "\e[48;5;${bc}m"; } + if ($txt) { $ret .= $txt . "\e[0m"; } return $ret; } # Get colors used for various output sections (memoized) -{ - my $static_config; +sub get_config_color { + my $str = shift(); - sub get_config_color { - my $str = shift(); + state $static_config; - my $ret = ""; - if ($static_config->{$str}) { - return $static_config->{$str}; - } + my $ret = ""; + if ($static_config->{$str}) { + return $static_config->{$str}; + } - #print color(15) . "Shelling out for color: '$str'\n" . color('reset'); - - if ($str eq "meta") { - # Default ANSI yellow - $ret = git_ansi_color(git_config('color.diff.meta')) || color(11); - } elsif ($str eq "reset") { - $ret = color("reset"); - } elsif ($str eq "add_line") { - # Default ANSI green - $ret = git_ansi_color(git_config('color.diff.new')) || color("2_bold"); - } elsif ($str eq "remove_line") { - # Default ANSI red - $ret = git_ansi_color(git_config('color.diff.old')) || color("1_bold"); - } elsif ($str eq "fragment") { - $ret = git_ansi_color(git_config('color.diff.frag')) || color("13_bold"); - } elsif ($str eq "last_function") { - $ret = git_ansi_color(git_config('color.diff.func')) || color("146_bold"); - } + #print color(15) . "Shelling out for color: '$str'\n" . color('reset'); + + if ($str eq "meta") { + # Default ANSI yellow + $ret = git_ansi_color(git_config('color.diff.meta')) || color(11); + } elsif ($str eq "reset") { + $ret = color("reset"); + } elsif ($str eq "add_line") { + # Default ANSI green + $ret = git_ansi_color(git_config('color.diff.new')) || color("2_bold"); + } elsif ($str eq "remove_line") { + # Default ANSI red + $ret = git_ansi_color(git_config('color.diff.old')) || color("1_bold"); + } elsif ($str eq "fragment") { + $ret = git_ansi_color(git_config('color.diff.frag')) || color("13_bold"); + } elsif ($str eq "last_function") { + $ret = git_ansi_color(git_config('color.diff.func')) || color("146_bold"); + } - # Cache (memoize) the entry for later - $static_config->{$str} = $ret; + # Cache (memoize) the entry for later + $static_config->{$str} = $ret; - return $ret; - } + return $ret; } # https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_colors_in_git @@ -974,6 +980,7 @@ sub set_ansi_color { } } +# Is the string 100% numeric sub is_numeric { my $s = shift(); @@ -984,6 +991,7 @@ sub is_numeric { return 0; } +# Does the string start with ANSI sub starts_with_ansi { my $str = shift(); @@ -1054,6 +1062,7 @@ sub show_debug_info { print "Operating System: $^O\n"; } +# Boolean to yes/no string sub yes_no { my $val = shift(); @@ -1073,6 +1082,7 @@ sub init_diff_highlight_colors { $DiffHighlight::OLD_HIGHLIGHT[1] = git_ansi_color(git_config('color.diff-highlight.oldhighlight')) || $DiffHighlight::OLD_HIGHLIGHT[1]; } +# Write a line to the debug log which is opened on the fly as-needed sub debug_log { my $log_line = shift(); my $file = "/tmp/diff-so-fancy.debug.log"; @@ -1088,12 +1098,16 @@ sub debug_log { return 1; } +# Count the number of context lines in the diff sub calculate_context_lines { my @lines = @_; my $count = 0; my $hunk_line = 0; + # Count the number of lines between the hunk line and the + # first + or - line foreach my $line (@lines) { + # Look for the hunk line before we start if ($line =~ /^${ansi_color_regex}(@@@* .+? @@@*)(.*)/) { $hunk_line = $count; } elsif ($hunk_line && $line =~ /^${ansi_color_regex}[+-]/) { diff --git a/hacking-and-testing.md b/hacking-and-testing.md index 10f8936..2620d17 100644 --- a/hacking-and-testing.md +++ b/hacking-and-testing.md @@ -17,7 +17,7 @@ cd ~/projects/catfabulator && git diff The tests use [bats-core](https://bats-core.readthedocs.io/en/latest/index.html), the Bash automated testing system. ```sh -# initalize the bats components +# initialize the bats components git submodule sync && git submodule update --init # run the test suite once: diff --git a/pro-tips.md b/pro-tips.md index 8b7aaa7..ddae8e8 100644 --- a/pro-tips.md +++ b/pro-tips.md @@ -35,6 +35,27 @@ application, it may be helpful to configure an alias: which can then be used as `git patch > changes.patch`. +## Improved colors for the highlighted bits + +The default Git colors are not optimal. The colors used for the screenshot were: + +```shell +git config --global color.ui true + +git config --global color.diff-highlight.oldNormal "red bold" +git config --global color.diff-highlight.oldHighlight "red bold 52" +git config --global color.diff-highlight.newNormal "green bold" +git config --global color.diff-highlight.newHighlight "green bold 22" + +git config --global color.diff.meta "11" +git config --global color.diff.frag "magenta bold" +git config --global color.diff.func "146 bold" +git config --global color.diff.commit "yellow bold" +git config --global color.diff.old "red bold" +git config --global color.diff.new "green bold" +git config --global color.diff.whitespace "red reverse" +``` + #### Moving around in the diff You can pre-seed your `less` pager with a search pattern so that you can move @@ -62,7 +83,7 @@ zinit load so-fancy/diff-so-fancy zplug "so-fancy/diff-so-fancy", as:command, use:bin/git-dsf ``` -# zgenom and others +### zgenom and others ```sh zgenom load so-fancy/diff-so-fancy diff --git a/test/bugs.bats b/test/bugs.bats index c209be7..233542e 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -75,3 +75,9 @@ teardown_file() { run printf "%s" "$output" assert_line --index 3 --partial "@ height" } + +@test "ANSI Reset without the zero (#469)" { + output=$( load_fixture "ansi_reset_no_number" | $diff_so_fancy ) + run printf "%s" "$output" + assert_line --index 5 --partial "History" +} diff --git a/test/fixtures/ansi_reset_no_number.diff b/test/fixtures/ansi_reset_no_number.diff new file mode 100644 index 0000000..7f51ab8 --- /dev/null +++ b/test/fixtures/ansi_reset_no_number.diff @@ -0,0 +1,9 @@ +diff --git a/history.md b/history.md +index f6776e0..a6b4546 100644 +--- a/history.md ++++ b/history.md +@@ -1,3 +1,3 @@ +-## History ++## Historyz +  + `diff-so-fancy` started as [a commit in paulirish's dotfiles](https://github.com/paulirish/dotfiles/commit/6743b907ff586c28cd36e08d1e1c634e2968893e#commitcomment-13349456), which grew into a [standalone script](https://github.com/paulirish/dotfiles/blob/63cb8193b0e66cf80ab6332477f1f52c7fbb9311/bin/diff-so-fancy). Later, [@stevemao](https://github.com/stevemao) brought it into its [own repo](https://github.com/so-fancy/diff-so-fancy) (here), and gave it the room to mature. It's quickly grown into a [widely collaborative project](https://github.com/so-fancy/diff-so-fancy/graphs/contributors). diff --git a/third_party/term-colors/term-colors.pl b/third_party/term-colors/term-colors.pl old mode 100644 new mode 100755 diff --git a/update-deps.sh b/update-deps.sh index cec889e..8156a81 100755 --- a/update-deps.sh +++ b/update-deps.sh @@ -1,4 +1,4 @@ #!/bin/bash -# initalize the bats components +# initialize the bats components git submodule sync && git submodule update --init