From 754f9dfbd2085eb8241d71808dda9592b463c5a8 Mon Sep 17 00:00:00 2001 From: Guillermo Ramos Date: Sat, 19 Jun 2021 10:45:37 +0200 Subject: [PATCH 01/41] Fix fg/bg extraction with l.t. 2 colors --- diff-so-fancy | 5 +++-- test/git_ansi_color.pl | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index 049aa37..603fbb2 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -918,14 +918,15 @@ sub git_ansi_color { if (grep { /bold/ } @parts) { push(@ansi_part, "1"); - @parts = grep { !/bold/ } @parts; # Remove from array } if (grep { /reverse/ } @parts) { push(@ansi_part, "7"); - @parts = grep { !/reverse/ } @parts; # Remove from array } + # Remove parts that aren't colors + @parts = grep { exists $colors->{$_} || is_numeric($_) } @parts; + my $fg = $parts[0] // ""; my $bg = $parts[1] // ""; diff --git a/test/git_ansi_color.pl b/test/git_ansi_color.pl index 3187069..e781de8 100644 --- a/test/git_ansi_color.pl +++ b/test/git_ansi_color.pl @@ -121,14 +121,15 @@ sub git_ansi_color { if (grep { /bold/ } @parts) { push(@ansi_part, "1"); - @parts = grep { !/bold/ } @parts; # Remove from array } if (grep { /reverse/ } @parts) { push(@ansi_part, "7"); - @parts = grep { !/reverse/ } @parts; # Remove from array } + # Remove parts that aren't colors + @parts = grep { exists $colors->{$_} || is_numeric($_) } @parts; + my $fg = $parts[0] // ""; my $bg = $parts[1] // ""; From 700af6e075d2a05f59b16b12fdf6464efd79d880 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Wed, 20 Oct 2021 13:19:31 -0700 Subject: [PATCH 02/41] test: load imports/setup in setup/setup_file bat callbacks --- test/bugs.bats | 17 ++++++++++++++--- test/diff-so-fancy.bats | 23 +++++++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/test/bugs.bats b/test/bugs.bats index 0e49052..69c019c 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -1,8 +1,19 @@ #!/usr/bin/env bats -load 'test_helper/bats-support/load' -load 'test_helper/bats-assert/load' -load 'test_helper/util' +# Used by both `setup_file` and `setup`, which are special bats callbacks. +__load_imports__() { + load 'test_helper/bats-support/load' + load 'test_helper/bats-assert/load' + load 'test_helper/util' +} + +setup_file() { + __load_imports__ +} + +setup() { + __load_imports__ +} # https://github.com/paulirish/dotfiles/commit/6743b907ff586c28cd36e08d1e1c634e2968893e#commitcomment-13459061 @test "All removed lines are present in diff" { diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 62d3a3d..e3f5110 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -1,13 +1,24 @@ #!/usr/bin/env bats -load 'test_helper/bats-support/load' -load 'test_helper/bats-assert/load' -load 'test_helper/util' +# Helper invoked by `setup_file` and `setup`, which are special bats callbacks. +__load_imports__() { + load 'test_helper/bats-support/load' + load 'test_helper/bats-assert/load' + load 'test_helper/util' +} + +setup_file() { + __load_imports__ +} -set_env +setup() { + __load_imports__ -# bats fails to handle our multiline result, so we save to $output ourselves -output=$( load_fixture "ls-function" | $diff_so_fancy ) + set_env + + # bats fails to handle our multiline result, so we save to $output ourselves + output=$( load_fixture "ls-function" | $diff_so_fancy ) +} @test "diff-so-fancy runs and exits without error" { load_fixture "ls-function" | $diff_so_fancy From 7fb648e8fa81528455ddc7c11212e605dae3926b Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Wed, 20 Oct 2021 13:21:41 -0700 Subject: [PATCH 03/41] test: cache initial setup vars --- test/diff-so-fancy.bats | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index e3f5110..370c5e3 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -9,15 +9,15 @@ __load_imports__() { setup_file() { __load_imports__ + set_env + # bats fails to handle our multiline result, so we save to $output ourselves + __dfs_cached_output="$( load_fixture "ls-function" | $diff_so_fancy )" + export __dfs_cached_output } setup() { __load_imports__ - - set_env - - # bats fails to handle our multiline result, so we save to $output ourselves - output=$( load_fixture "ls-function" | $diff_so_fancy ) + output="${__dfs_cached_output}" } @test "diff-so-fancy runs and exits without error" { From f156545804e49f4b604e71e277356ff3c6a8bcd7 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Tue, 19 Oct 2021 20:29:26 -0700 Subject: [PATCH 04/41] test: use completely isolated, temporary GIT_CONFIG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This writes a temp git config file during setup/teardown, and exports GIT_CONFIG=… to that and sets GIT_CONFIG_NOSYSTEM=1. This ensures that any git invocations _only_ use that configuration. Note that none of the tests currently test anything other than the default config; however, if they do, the generation of this test config should be moved into `setup()` rather than `setup_file()` so that it can be modified and restored between tests. --- diff-so-fancy | 14 -------------- test/bugs.bats | 5 +++++ test/diff-so-fancy.bats | 11 ++++++++--- test/test_helper/util.bash | 39 ++++++++++++++++++++++++++++---------- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index 049aa37..5fd758f 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -490,26 +490,12 @@ sub git_config_boolean { my $search_key = lc($_[0] || ""); my $default_value = lc($_[1] || 0); # Default to false - # If we're in a unit test, use the default (don't read the users config) - if (in_unit_test()) { - return boolean($default_value); - } - my $result = git_config($search_key,$default_value); my $ret = boolean($result); return $ret; } -# Check if we're inside of BATS -sub in_unit_test { - if ($ENV{BATS_CWD}) { - return 1; - } else { - return 0; - } -} - sub get_less_charset { my @less_char_vars = ("LESSCHARSET", "LESSCHARDEF", "LC_ALL", "LC_CTYPE", "LANG"); foreach my $key (@less_char_vars) { diff --git a/test/bugs.bats b/test/bugs.bats index 69c019c..d0934ec 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -9,12 +9,17 @@ __load_imports__() { setup_file() { __load_imports__ + setup_default_dsf_git_config } setup() { __load_imports__ } +teardown_file() { + teardown_default_dsf_git_config +} + # https://github.com/paulirish/dotfiles/commit/6743b907ff586c28cd36e08d1e1c634e2968893e#commitcomment-13459061 @test "All removed lines are present in diff" { output=$( load_fixture "chromium-modaltoelement" | $diff_so_fancy ) diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 370c5e3..31d9a56 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -10,14 +10,19 @@ __load_imports__() { setup_file() { __load_imports__ set_env + setup_default_dsf_git_config # bats fails to handle our multiline result, so we save to $output ourselves - __dfs_cached_output="$( load_fixture "ls-function" | $diff_so_fancy )" - export __dfs_cached_output + __dsf_cached_output="$( load_fixture "ls-function" | $diff_so_fancy )" + export __dsf_cached_output } setup() { __load_imports__ - output="${__dfs_cached_output}" + output="${__dsf_cached_output}" +} + +teardown_file() { + teardown_default_dsf_git_config } @test "diff-so-fancy runs and exits without error" { diff --git a/test/test_helper/util.bash b/test/test_helper/util.bash index 440d3bd..dbad4b1 100644 --- a/test/test_helper/util.bash +++ b/test/test_helper/util.bash @@ -10,17 +10,36 @@ set_env() { export LC_CTYPE="en_US.UTF-8" } +dsf_test_git_config() { + printf '%s/gitconfig' "${BATS_TMPDIR}" +} # applying colors so ANSI color values will match # FIXME: not everyone will have these set, so we need to test for that. -git config color.diff.meta "227" -git config color.diff.frag "magenta bold" -git config color.diff.commit "227 bold" -git config color.diff.old "red bold" -git config color.diff.new "green bold" -git config color.diff.whitespace "red reverse" +setup_default_dsf_git_config() { + GIT_CONFIG="$(dsf_test_git_config)" || return $? + cat > "${GIT_CONFIG}" < Date: Mon, 18 Oct 2021 15:41:04 -0700 Subject: [PATCH 05/41] fix: over-permissive regex for added/deleted file meta header The previous pattern uselessly included `.*`, unlike all the other patterns, and so would erroneously match on actual diff content lines. Noticed this because the line itself was filtered out of diffs in this codebase. This also tightens the pattern since the file mode will always be six octal (0-7) chars; and in the git codebase the format string is: "%s%snew file mode %06o%s\n" --- diff-so-fancy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index 049aa37..903be52 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -303,7 +303,7 @@ sub do_dsf_stuff { ################################### # Remove any new file permissions # ################################### - } elsif ($remove_file_add_header && $line =~ /^${ansi_color_regex}.*new file mode/) { + } elsif ($remove_file_add_header && $line =~ /^${ansi_color_regex}new file mode [0-7]{6}/) { # Don't print the line (i.e. remove it from the output); $last_file_mode = "add"; if ($patch_mode) { @@ -312,7 +312,7 @@ sub do_dsf_stuff { ###################################### # Remove any delete file permissions # ###################################### - } elsif ($remove_file_delete_header && $line =~ /^${ansi_color_regex}deleted file mode/) { + } elsif ($remove_file_delete_header && $line =~ /^${ansi_color_regex}deleted file mode [0-7]{6}/) { # Don't print the line (i.e. remove it from the output); $last_file_mode = "delete"; if ($patch_mode) { From 1a0ad54d77635c6c8a2b994c3df8cde2db82748c Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Fri, 22 Oct 2021 21:35:37 -0700 Subject: [PATCH 06/41] Bump the version so it's clear we're working on new stuff --- diff-so-fancy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff-so-fancy b/diff-so-fancy index 636a977..5fc8241 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -1,6 +1,6 @@ #!/usr/bin/env perl -my $VERSION = "1.4.2"; +my $VERSION = "1.4.4"; ################################################################################# From c0f7c221d9376633c3267d4707467a57c4ec8dd2 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Wed, 3 Nov 2021 10:48:36 -0700 Subject: [PATCH 07/41] Bump the bats stuff to v1.5.0 --- test/bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats b/test/bats index 49b377a..a8b8d0d 160000 --- a/test/bats +++ b/test/bats @@ -1 +1 @@ -Subproject commit 49b377a751e6f9379abfdfb3dfa3aafabd8495a1 +Subproject commit a8b8d0dc7a05abe10c8511fe5041c137e06d18bf From 3ba29c9f70877576229db9f3ec6d7be2c418dc2f Mon Sep 17 00:00:00 2001 From: vladislav doster Date: Fri, 5 Nov 2021 19:47:25 -0500 Subject: [PATCH 08/41] (maint) update `pro-tips.md` Last week, @psprint deleted all `zinit` related source code. More info can be [found here](https://github.com/zdharma-continuum/I_WANT_TO_HELP) - update `zdharma` URLs to `zdharma-continuum` URLS. - apply consistent markdown formatting - add language hints to code fences --- pro-tips.md | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/pro-tips.md b/pro-tips.md index 80404f4..b1ee2f7 100644 --- a/pro-tips.md +++ b/pro-tips.md @@ -1,18 +1,21 @@ -## Pro-tips +# Pro-tips -#### One-off fanciness or a specific diff-so-fancy alias +## One-off fanciness or a specific diff-so-fancy alias You can do also do a one-off: + ```shell git diff --color | diff-so-fancy ``` + or configure an alias and a corresponding pager to use `diff-so-fancy`: + ```shell git config --global alias.dsf "diff --color" git config --global pager.dsf "diff-so-fancy | less --tabs=4 -RFXS" ``` -#### Opting-out +## Opting-out Sometimes you will want to bypass diff-so-fancy. Use `--no-pager` for that: @@ -20,49 +23,52 @@ Sometimes you will want to bypass diff-so-fancy. Use `--no-pager` for that: git --no-pager diff ``` -#### Raw patches +## Raw patches As a shortcut for a 'normal' diff to save as a patch for emailing or later application, it may be helpful to configure an alias: + ```ini [alias] patch = !git --no-pager diff --no-color ``` + which can then be used as `git patch > changes.patch`. #### Moving around in the diff -You can pre-seed your `less` pager with a search pattern, so you can move +You can pre-seed your `less` pager with a search pattern so that you can move between files with `n`/`N` keys: + ```ini [pager] diff = diff-so-fancy | less --tabs=4 -RFXS --pattern '^(Date|added|deleted|modified): ' ``` -#### Zsh plugin providing diff-so-fancy +## Zsh plugin providing diff-so-fancy -Zsh plugin [zdharma/zsh-diff-so-fancy](https://github.com/zdharma/zsh-diff-so-fancy) has this -project as a submodule so installing the plugin installs `diff-so-fancy`. The plugin provides -subcommand `git dsf` out of the box. Installation with Zinit, Zplug and Zgen: +Zsh plugin [zdharma-continuum/zsh-diff-so-fancy](https://github.com/zdharma-continuum/zsh-diff-so-fancy) has this +project as a submodule, so installing the plugin installs `diff-so-fancy`. The plugin provides +the subcommand `git dsf` out of the box. Installation with Zinit, Zplug, and Zgen: ```zsh # zinit zinit ice lucid as"program" pick"bin/git-dsf" -zinit load zdharma/zsh-diff-so-fancy +zinit load zdharma-continuum/zsh-diff-so-fancy -# Or zplug -zplug "zdharma/zsh-diff-so-fancy", as:command, use:bin/git-dsf +# zplug +zplug "zdharma-continuum/zsh-diff-so-fancy", as:command, use:bin/git-dsf -# Or zgen and others -zgen zdharma/zsh-diff-so-fancy +# zgen and others +zgen zdharma-continuum/zsh-diff-so-fancy ``` -#### `hg` configuration +## `hg` configuration You can configure `hg diff` output to use `diff-so-fancy` by adding this alias to your `hgrc` file: -``` +```ini [alias] -diff = !HGPLAIN=1 $HG diff --pager=on --config pager.pager=diff-so-fancy $@ + diff = !HGPLAIN=1 $HG diff --pager=on --config pager.pager=diff-so-fancy $@ ``` From 2cbbef68d181f7dca4cdb1716625a87ab1676295 Mon Sep 17 00:00:00 2001 From: KopfKrieg Date: Sun, 23 Jan 2022 00:49:41 +0100 Subject: [PATCH 09/41] Move comparison image into the repository, fix white borders --- README.md | 2 +- diff-so-fancy.png | Bin 0 -> 151309 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 diff-so-fancy.png diff --git a/README.md b/README.md index ebf152c..f5d4f9f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` -![diff-highlight vs diff-so-fancy](https://user-images.githubusercontent.com/3429760/32387617-44c873da-c082-11e7-829c-6160b853adcb.png) +![diff-highlight vs diff-so-fancy](diff-so-fancy.png) ## Install diff --git a/diff-so-fancy.png b/diff-so-fancy.png new file mode 100644 index 0000000000000000000000000000000000000000..869e92cd55fe5b2c5097ba223973eced7f6be1cb GIT binary patch literal 151309 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≪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 =Os?#dR5p($?O6r^$yc^b6zYK?Wb& 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 literal 0 HcmV?d00001 From e65b8b93a91237a94a791b63974a52639913624e Mon Sep 17 00:00:00 2001 From: KopfKrieg Date: Sun, 23 Jan 2022 01:04:06 +0100 Subject: [PATCH 10/41] Added Fedora COPR repository to the installation section of the README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebf152c..357d89f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), and [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/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian), and as [Fedora COPR repository](https://copr.fedorainfracloud.org/coprs/kopfkrieg/diff-so-fancy/). 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. From 3c22692f16856de81b183f10d103c2ad4130ae8c Mon Sep 17 00:00:00 2001 From: "Florian \"KopfKrieg" Date: Sun, 23 Jan 2022 18:04:53 +0100 Subject: [PATCH 11/41] =?UTF-8?q?README.md:=20"as"=20=E2=86=92=20"in=20the?= =?UTF-8?q?"=20(improved=20readability)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Oliver Ford --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 357d89f..0c02f9f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian), and as [Fedora COPR repository](https://copr.fedorainfracloud.org/coprs/kopfkrieg/diff-so-fancy/). +`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/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian), and in the [Fedora COPR repository](https://copr.fedorainfracloud.org/coprs/kopfkrieg/diff-so-fancy/). 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. From dff9de221539ee5ec8d0dda3bcbb836bf26ef04f Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Thu, 7 Apr 2022 07:11:00 -0700 Subject: [PATCH 12/41] Bump the bats testing pointer --- test/bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bats b/test/bats index a8b8d0d..5c3f335 160000 --- a/test/bats +++ b/test/bats @@ -1 +1 @@ -Subproject commit a8b8d0dc7a05abe10c8511fe5041c137e06d18bf +Subproject commit 5c3f335e9b2fed5d89306398fb4e258f8fa06666 From 8670353092aab15e414c5dd96faeefb8809e4af7 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Thu, 7 Apr 2022 14:29:26 -0700 Subject: [PATCH 13/41] Use autoload to be more "smart" about debug print --- diff-so-fancy | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index 42a04b8..405c26c 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -1075,20 +1075,26 @@ sub debug_log { return 1; } -# Enable k() and kd() if there is a DSF_DEBUG environment variable -BEGIN { - if ($ENV{"DSF_DEBUG"}) { - require Data::Dump::Color; - *k = sub { Data::Dump::Color::dd(@_) }; - *kd = sub { +# Borrowed from: https://www.perturb.org/display/1097_Perl_detect_if_a_module_is_installed_before_using_it.html +sub AUTOLOAD { + our $AUTOLOAD; # keep 'use strict' happy + + if ($AUTOLOAD eq 'main::k' || $AUTOLOAD eq 'main::kd') { + if (eval { require Data::Dump::Color }) { + *k = sub { Data::Dump::Color::dd(@_) }; + } else { + require Data::Dumper; + *k = sub { print Data::Dumper::Dumper(@_) }; + } + + sub kd { k(@_); printf("Died at %2\$s line #%3\$s\n",caller()); exit(15); } - } else { - *k = sub {}; - *kd = sub {}; + + eval($AUTOLOAD . '(@_)'); } } From 6a301bbba5686e07b9a38a7a9a3f12cedf2e3fe4 Mon Sep 17 00:00:00 2001 From: brewsfab <19392469+brewsfab@users.noreply.github.com> Date: Sun, 19 Jun 2022 05:35:48 +0900 Subject: [PATCH 14/41] Support vanilla diff recursive flag (#436) * Support vanilla diff recursive flag * Adjust the regex patterns and explanation * Simplify recursive regex and add comment --- README.md | 9 +++++ diff-so-fancy | 6 +-- test/diff-so-fancy.bats | 24 ++++++++++++ .../recursive_default_as_mercurial.diff | 38 +++++++++++++++++++ .../recursive_longhand_as_mercurial.diff | 38 +++++++++++++++++++ 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/recursive_default_as_mercurial.diff create mode 100644 test/fixtures/recursive_longhand_as_mercurial.diff diff --git a/README.md b/README.md index 3931f0c..2d55448 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,15 @@ Use `-u` with `diff` for unified output, and pipe the output to `diff-so-fancy`: diff -u file_a file_b | diff-so-fancy ``` +It also supports the recursive mode of diff with `-r` or `--recursive` as **first argument** + +```shell +diff -r -u folder_a folder_b | diff-so-fancy +``` + +```shell +diff --recursive -u folder_a folder_b | diff-so-fancy +``` ## Options ### markEmptyLines diff --git a/diff-so-fancy b/diff-so-fancy index 405c26c..e729b20 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -192,11 +192,11 @@ sub do_dsf_stuff { ######################### # Look for the filename # ######################### - # $4 $5 - } elsif ($line =~ /^${ansi_color_regex}diff (-r|--git|--cc) (.*?)(\e| b\/|$)/) { + # $4 $5 + } elsif ($line =~ /^${ansi_color_regex}diff (-r|--recursive|--git|--cc) (.*?)(\e| b\/|$)/) { # Mercurial looks like: diff -r 82e55d328c8c hello.c - if ($4 eq "-r") { + if ($4 eq "-r" || $4 eq "--recursive") { $is_mercurial = 1; $meta_color = get_config_color("meta"); # Git looks like: diff --git a/diff-so-fancy b/diff-so-fancy diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 31d9a56..463cce6 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -247,3 +247,27 @@ teardown_file() { assert_line --index 1 --partial "modified: doc/manual.xml.head" assert_line --index 3 --partial "@ doc/manual.xml.head:8355 @" } + +@test "recursive vanilla diff -r -bu as Mercurial" { + output=$( load_fixture "recursive_default_as_mercurial" | $diff_so_fancy ) + run printf "%s" "$output" + + assert_line --index 1 --partial "renamed:" + assert_line --index 3 --partial "@ language/app.py:4 @" + assert_line --index 19 --partial "renamed:" + assert_line --index 21 --partial "@ language/__init__.py:1 @" + assert_line --index 25 --partial "renamed:" + assert_line --index 27 --partial "@ language/README.md:1 @" +} + +@test "recursive vanilla diff --recursive -u as Mercurial" { + output=$( load_fixture "recursive_longhand_as_mercurial" | $diff_so_fancy ) + run printf "%s" "$output" + + assert_line --index 1 --partial "renamed:" + assert_line --index 3 --partial "@ language/app.py:4 @" + assert_line --index 19 --partial "renamed:" + assert_line --index 21 --partial "@ language/__init__.py:1 @" + assert_line --index 25 --partial "renamed:" + assert_line --index 27 --partial "@ language/README.md:1 @" +} diff --git a/test/fixtures/recursive_default_as_mercurial.diff b/test/fixtures/recursive_default_as_mercurial.diff new file mode 100644 index 0000000..32dc000 --- /dev/null +++ b/test/fixtures/recursive_default_as_mercurial.diff @@ -0,0 +1,38 @@ +diff -r -bu core/app.py language/app.py +--- core/app.py 2022-06-08 13:42:10.658920131 +0900 ++++ language/app.py 2022-06-08 12:07:22.773069512 +0900 +@@ -1,13 +1,13 @@ +-from flask import Flask, abort +-from . import CORE_MODULES ++from flask import Flask ++from . import SECTION + + app = Flask(__name__) + +-@app.route('/') ++@app.route(f'/{SECTION}/') + def index(name): +- if name in CORE_MODULES: +- return "Welcome to the documentation for the core module" +- abort(404) ++ return f"Welcome to the documentation for {name}" + ++if __name__ == "__main__": ++ app.run(host="0.0.0.0",port=3000) + + +diff -r -bu core/__init__.py language/__init__.py +--- core/__init__.py 2022-06-08 12:16:35.203331282 +0900 ++++ language/__init__.py 2022-06-08 12:03:32.464264288 +0900 +@@ -1 +1 @@ +-CORE_MODULES=['base','utils','status'] ++SECTION="language" +diff -r -bu core/README.md language/README.md +--- core/README.md 2022-06-08 13:52:56.962174912 +0900 ++++ language/README.md 2022-06-08 13:52:39.498090643 +0900 +@@ -1,4 +1,4 @@ +-# Core ++# Language + + ## Installation + diff --git a/test/fixtures/recursive_longhand_as_mercurial.diff b/test/fixtures/recursive_longhand_as_mercurial.diff new file mode 100644 index 0000000..c9860d0 --- /dev/null +++ b/test/fixtures/recursive_longhand_as_mercurial.diff @@ -0,0 +1,38 @@ +diff --recursive -u core/app.py language/app.py +--- core/app.py 2022-06-08 13:42:10.658920131 +0900 ++++ language/app.py 2022-06-08 12:07:22.773069512 +0900 +@@ -1,13 +1,13 @@ +-from flask import Flask, abort +-from . import CORE_MODULES ++from flask import Flask ++from . import SECTION + + app = Flask(__name__) + +-@app.route('/') ++@app.route(f'/{SECTION}/') + def index(name): +- if name in CORE_MODULES: +- return "Welcome to the documentation for the core module" +- abort(404) ++ return f"Welcome to the documentation for {name}" + ++if __name__ == "__main__": ++ app.run(host="0.0.0.0",port=3000) + + +diff --recursive -u core/__init__.py language/__init__.py +--- core/__init__.py 2022-06-08 12:16:35.203331282 +0900 ++++ language/__init__.py 2022-06-08 12:03:32.464264288 +0900 +@@ -1 +1 @@ +-CORE_MODULES=['base','utils','status'] ++SECTION="language" +diff --recursive -u core/README.md language/README.md +--- core/README.md 2022-06-08 13:52:56.962174912 +0900 ++++ language/README.md 2022-06-08 13:52:39.498090643 +0900 +@@ -1,4 +1,4 @@ +-# Core ++# Language + + ## Installation + From c1660def5c60096e8422694debc924009c35ba9b Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Sat, 18 Jun 2022 13:45:08 -0700 Subject: [PATCH 15/41] Move a bug/feature test to the bugs.test file --- test/bugs.bats | 24 ++++++++++++++++++++++++ test/diff-so-fancy.bats | 24 ------------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/bugs.bats b/test/bugs.bats index d0934ec..203e2ac 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -45,3 +45,27 @@ teardown_file() { assert_line --index 5 --partial "5;22m" # green added line assert_line --index 8 --partial "5;52m" # red removed line } + +@test "recursive vanilla diff -r -bu as Mercurial (#436)" { + output=$( load_fixture "recursive_default_as_mercurial" | $diff_so_fancy ) + run printf "%s" "$output" + + assert_line --index 1 --partial "renamed:" + assert_line --index 3 --partial "@ language/app.py:4 @" + assert_line --index 19 --partial "renamed:" + assert_line --index 21 --partial "@ language/__init__.py:1 @" + assert_line --index 25 --partial "renamed:" + assert_line --index 27 --partial "@ language/README.md:1 @" +} + +@test "recursive vanilla diff --recursive -u as Mercurial (#436)" { + output=$( load_fixture "recursive_longhand_as_mercurial" | $diff_so_fancy ) + run printf "%s" "$output" + + assert_line --index 1 --partial "renamed:" + assert_line --index 3 --partial "@ language/app.py:4 @" + assert_line --index 19 --partial "renamed:" + assert_line --index 21 --partial "@ language/__init__.py:1 @" + assert_line --index 25 --partial "renamed:" + assert_line --index 27 --partial "@ language/README.md:1 @" +} diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 463cce6..31d9a56 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -247,27 +247,3 @@ teardown_file() { assert_line --index 1 --partial "modified: doc/manual.xml.head" assert_line --index 3 --partial "@ doc/manual.xml.head:8355 @" } - -@test "recursive vanilla diff -r -bu as Mercurial" { - output=$( load_fixture "recursive_default_as_mercurial" | $diff_so_fancy ) - run printf "%s" "$output" - - assert_line --index 1 --partial "renamed:" - assert_line --index 3 --partial "@ language/app.py:4 @" - assert_line --index 19 --partial "renamed:" - assert_line --index 21 --partial "@ language/__init__.py:1 @" - assert_line --index 25 --partial "renamed:" - assert_line --index 27 --partial "@ language/README.md:1 @" -} - -@test "recursive vanilla diff --recursive -u as Mercurial" { - output=$( load_fixture "recursive_longhand_as_mercurial" | $diff_so_fancy ) - run printf "%s" "$output" - - assert_line --index 1 --partial "renamed:" - assert_line --index 3 --partial "@ language/app.py:4 @" - assert_line --index 19 --partial "renamed:" - assert_line --index 21 --partial "@ language/__init__.py:1 @" - assert_line --index 25 --partial "renamed:" - assert_line --index 27 --partial "@ language/README.md:1 @" -} From 6fc812224125221e2409fe8a26ae3c246bdc2a07 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Tue, 30 Aug 2022 15:07:53 -0700 Subject: [PATCH 16/41] Potential fix for #438 --- diff-so-fancy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index e729b20..e982ba0 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -931,7 +931,7 @@ sub git_ansi_color { # It's a simple 16 color OG ansi } elsif ($fg) { my $bright = $fg =~ s/bright//; - my $color_num = $colors->{$fg} + 30; + my $color_num = ($colors->{$fg} // 0) + 30; if ($bright) { $color_num += 60; } # Set bold @@ -952,7 +952,7 @@ sub git_ansi_color { # It's a simple 16 color OG ansi } elsif ($bg) { my $bright = $bg =~ s/bright//; - my $color_num = $colors->{$bg} + 40; + my $color_num = ($colors->{$bg} // 0) + 40; if ($bright) { $color_num += 60; } # Set bold From 796daa4c5f0c0faf6c9d60c009b1a46701a9a0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Lajoie?= Date: Mon, 12 Sep 2022 22:45:30 +0200 Subject: [PATCH 17/41] Generate bright colors (#444) --- diff-so-fancy | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index e982ba0..fa7fc59 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -900,6 +900,9 @@ sub git_ansi_color { 'cyan' => 6, 'white' => 7, }; + for my $k (keys %{ $colors }) { + $colors->{"bright" . $k} = $colors->{$k} + 60; + } my @ansi_part = (); @@ -930,11 +933,7 @@ sub git_ansi_color { } # It's a simple 16 color OG ansi } elsif ($fg) { - my $bright = $fg =~ s/bright//; my $color_num = ($colors->{$fg} // 0) + 30; - - if ($bright) { $color_num += 60; } # Set bold - push(@ansi_part, $color_num); } @@ -951,11 +950,7 @@ sub git_ansi_color { } # It's a simple 16 color OG ansi } elsif ($bg) { - my $bright = $bg =~ s/bright//; my $color_num = ($colors->{$bg} // 0) + 40; - - if ($bright) { $color_num += 60; } # Set bold - push(@ansi_part, $color_num); } From 483d51706b5f8f750468c6e6555dccb2c00c74ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Lajoie?= Date: Mon, 12 Sep 2022 22:47:50 +0200 Subject: [PATCH 18/41] Add dim and underline as Select Graphic Rendition (#442) --- diff-so-fancy | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/diff-so-fancy b/diff-so-fancy index fa7fc59..0a5f775 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -910,6 +910,14 @@ sub git_ansi_color { push(@ansi_part, "1"); } + if (grep { /dim/ } @parts) { + push(@ansi_part, "2"); + } + + if (grep { /ul/ } @parts) { + push(@ansi_part, "4"); + } + if (grep { /reverse/ } @parts) { push(@ansi_part, "7"); } From 0c877075aaaed8657c3f232d8c33be3b4b119c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Lajoie?= Date: Mon, 12 Sep 2022 22:48:34 +0200 Subject: [PATCH 19/41] Reset color instead of forcing to bold for function (#441) --- diff-so-fancy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff-so-fancy b/diff-so-fancy index 0a5f775..6218e6e 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -300,7 +300,7 @@ sub do_dsf_stuff { print $frag_color; } - print "@ $last_file_seen:$start_line \@${bold}${last_function_color}${remain}${reset_color}\n"; + print "@ $last_file_seen:$start_line \@${reset_color}${last_function_color}${remain}${reset_color}\n"; ################################### # Remove any new file permissions # ################################### From 2d519df741ae5d173046fea02afdc9c69e184569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Lajoie?= Date: Mon, 12 Sep 2022 22:54:37 +0200 Subject: [PATCH 20/41] Add test for highlight and last function (#445) --- test/diff-so-fancy.bats | 7 +++++++ test/test_helper/util.bash | 1 + 2 files changed, 8 insertions(+) diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 31d9a56..9512ea3 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -247,3 +247,10 @@ teardown_file() { assert_line --index 1 --partial "modified: doc/manual.xml.head" assert_line --index 3 --partial "@ doc/manual.xml.head:8355 @" } + +@test "Functionnal part with bright color" { + output=$( load_fixture "move_with_content_change" | $diff_so_fancy ) + run printf "%s" "$output" + assert_line --index 3 --partial "@ height" +} + diff --git a/test/test_helper/util.bash b/test/test_helper/util.bash index dbad4b1..7b58a7b 100644 --- a/test/test_helper/util.bash +++ b/test/test_helper/util.bash @@ -26,6 +26,7 @@ setup_default_dsf_git_config() { old = red bold new = green bold whitespace = red reverse + func = brightyellow [color "diff-highlight"] oldNormal = red bold From bab2911457a0feec80a809aa13487c433f004c74 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Mon, 12 Sep 2022 13:57:44 -0700 Subject: [PATCH 21/41] Add a comment to help later --- diff-so-fancy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/diff-so-fancy b/diff-so-fancy index 6218e6e..18bd990 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -890,6 +890,7 @@ sub git_ansi_color { if (!@parts) { return ''; } + my $colors = { 'black' => 0, 'red' => 1, @@ -900,6 +901,8 @@ sub git_ansi_color { 'cyan' => 6, 'white' => 7, }; + + # Bright colors are just offsets from the "regular" color for my $k (keys %{ $colors }) { $colors->{"bright" . $k} = $colors->{$k} + 60; } From 7dec9311fa69192bfaa7c513e303cd2e7eae28b7 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Mon, 12 Sep 2022 13:59:48 -0700 Subject: [PATCH 22/41] Move a test to the bugs testing file --- test/bugs.bats | 6 ++++++ test/diff-so-fancy.bats | 7 ------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/bugs.bats b/test/bugs.bats index 203e2ac..a148685 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -69,3 +69,9 @@ teardown_file() { assert_line --index 25 --partial "renamed:" assert_line --index 27 --partial "@ language/README.md:1 @" } + +@test "Functional part with bright color (#444)" { + output=$( load_fixture "move_with_content_change" | $diff_so_fancy ) + run printf "%s" "$output" + assert_line --index 3 --partial "@ height" +} diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 9512ea3..31d9a56 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -247,10 +247,3 @@ teardown_file() { assert_line --index 1 --partial "modified: doc/manual.xml.head" assert_line --index 3 --partial "@ doc/manual.xml.head:8355 @" } - -@test "Functionnal part with bright color" { - output=$( load_fixture "move_with_content_change" | $diff_so_fancy ) - run printf "%s" "$output" - assert_line --index 3 --partial "@ height" -} - From ac0cbe2443a5a8378857fa2e41b3594903ec5ae9 Mon Sep 17 00:00:00 2001 From: Vladimir Kirov Date: Thu, 3 Nov 2022 18:21:47 +0200 Subject: [PATCH 23/41] bump required perl version (#447) - /u is added in perl 5.14 - [link to perl5140delta](https://perldoc.perl.org/5.14.4/perl5140delta#/d,-/l,-/u,-and-/a-modifiers) --- diff-so-fancy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff-so-fancy b/diff-so-fancy index 18bd990..0b0f439 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -4,7 +4,7 @@ my $VERSION = "1.4.4"; ################################################################################# -use v5.010; # Require Perl 5.10 for 'state' variables +use v5.014; # Require Perl 5.14 for 'state' variables and /u in regexes use warnings FATAL => 'all'; use strict; From f67767be40620095e13781655e42ce30d1e2858d Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Mon, 28 Nov 2022 10:05:01 -0800 Subject: [PATCH 24/41] Code simplifications to address #448 --- third_party/build_fatpack/build.pl | 2 +- third_party/cli_bench/cli_bench.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/build_fatpack/build.pl b/third_party/build_fatpack/build.pl index 942527f..26993af 100755 --- a/third_party/build_fatpack/build.pl +++ b/third_party/build_fatpack/build.pl @@ -40,7 +40,7 @@ my $cmd = "fatpack pack $input_file 2>/dev/null > $output_file"; my $exit = system($cmd); -$exit = $exit >> 8; +$exit >>= 8; rmdir("fatlib"); # fatpack leaves empty fatlib dirs so we remove them my $size = -s $output_file; diff --git a/third_party/cli_bench/cli_bench.pl b/third_party/cli_bench/cli_bench.pl index 9f05ee2..7c3aaee 100644 --- a/third_party/cli_bench/cli_bench.pl +++ b/third_party/cli_bench/cli_bench.pl @@ -114,7 +114,7 @@ sub average { } my $count = scalar(@_); - $ret = $ret / $count; + $ret /= $count; return $ret; } From f2e94082e2fc76de2c90dcf7613812f71d97d50c Mon Sep 17 00:00:00 2001 From: Vitaly Zdanevich Date: Wed, 15 Feb 2023 20:25:31 +0400 Subject: [PATCH 25/41] README: distros: add Gentoo (#456) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9881574..94358ba 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), and [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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/7833a73834c5a4ffe060acd576bfdeeef2a9d5b8/app-misc/diff-so-fancy), [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' own repositories/issue trackers where applicable. From 1f0dd538ed1a199e7f94e847ec8e59ca3cf87215 Mon Sep 17 00:00:00 2001 From: Vitaly Zdanevich Date: Wed, 15 Feb 2023 20:31:16 +0400 Subject: [PATCH 26/41] README: Gentoo package link: fix from commit to master (#457) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 94358ba..b59d992 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/7833a73834c5a4ffe060acd576bfdeeef2a9d5b8/app-misc/diff-so-fancy), [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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/master/app-misc/diff-so-fancy), [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' own repositories/issue trackers where applicable. From d7dcc1715f5bffc575183c16a2f458caa37cfa1b Mon Sep 17 00:00:00 2001 From: mikaello <2505178+mikaello@users.noreply.github.com> Date: Mon, 27 Feb 2023 14:43:33 +0100 Subject: [PATCH 27/41] docs: fix url to Nix package --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b59d992..9c393cb 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/master/app-misc/diff-so-fancy), [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), and 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 community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/master/app-misc/diff-so-fancy), [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' own repositories/issue trackers where applicable. From e2d91b2147964659b72352835dbd938623ce3093 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Sun, 5 Mar 2023 10:36:39 -0800 Subject: [PATCH 28/41] Update some unit tests to have the correct context offset lines --- test/bugs.bats | 4 ++-- test/diff-so-fancy.bats | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/bugs.bats b/test/bugs.bats index a148685..c209be7 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -51,7 +51,7 @@ teardown_file() { run printf "%s" "$output" assert_line --index 1 --partial "renamed:" - assert_line --index 3 --partial "@ language/app.py:4 @" + assert_line --index 3 --partial "@ language/app.py:1 @" assert_line --index 19 --partial "renamed:" assert_line --index 21 --partial "@ language/__init__.py:1 @" assert_line --index 25 --partial "renamed:" @@ -63,7 +63,7 @@ teardown_file() { run printf "%s" "$output" assert_line --index 1 --partial "renamed:" - assert_line --index 3 --partial "@ language/app.py:4 @" + assert_line --index 3 --partial "@ language/app.py:1 @" assert_line --index 19 --partial "renamed:" assert_line --index 21 --partial "@ language/__init__.py:1 @" assert_line --index 25 --partial "renamed:" diff --git a/test/diff-so-fancy.bats b/test/diff-so-fancy.bats index 31d9a56..cddac9d 100644 --- a/test/diff-so-fancy.bats +++ b/test/diff-so-fancy.bats @@ -187,8 +187,10 @@ teardown_file() { @test "Reworked hunks" { output=$( load_fixture "file-moves" | $diff_so_fancy ) - assert_output --partial '@ square.yml:4 @' - assert_output --partial '@ package.json:1 @' + run printf "%s" "$output" + + assert_line --index 46 --partial "@ package.json:1 @" + assert_line --index 79 --partial "@ square.yml:1 @" } @test "Reworked hunks (noprefix)" { From 022a86aa4f92e4fce358a863c17be886bcc77875 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Sun, 5 Mar 2023 10:42:41 -0800 Subject: [PATCH 29/41] Attempt to calculate context lines for #460 --- diff-so-fancy | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index 0b0f439..e440fda 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -26,6 +26,7 @@ my $use_unicode_dash_for_ruler = git_config_boolean("diff-so-fancy.useUnicodeRul my $ruler_width = git_config("diff-so-fancy.rulerWidth", undef); my $git_strip_prefix = git_config_boolean("diff.noprefix","false"); my $has_stdin = has_stdin(); +my $CONTEXT_LINES = undef; # Number of lines of context diff used my $ansi_regex = qr/\e\[([0-9]{1,3}(;[0-9]{1,3}){0,10})[mK]/; my $ansi_color_regex = qr/(${ansi_regex})?/; @@ -139,6 +140,11 @@ do_dsf_stuff(\@lines); sub do_dsf_stuff { my $input = shift(); + # Calculate the context lines the first time + if (!defined $CONTEXT_LINES) { + $CONTEXT_LINES = calculate_context_lines(@lines); + } + #print STDERR "START -------------------------------------------------\n"; #print STDERR join("",@$input); #print STDERR "END ---------------------------------------------------\n"; @@ -534,16 +540,14 @@ sub start_line_calc { return 1; } - # Git defaults to three lines of context - my $default_context_lines = 3; # Three lines on either side, and the line itself = 7 - my $expected_context = ($default_context_lines * 2 + 1); + my $expected_context = ($CONTEXT_LINES * 2 + 1); # The first three lines if ($line_num == 1 && $diff_context < $expected_context) { - $ret = $diff_context - $default_context_lines; + $ret = $diff_context - $CONTEXT_LINES; } else { - $ret = $line_num + $default_context_lines; + $ret = $line_num + $CONTEXT_LINES; } if ($ret < 1) { @@ -1081,6 +1085,27 @@ sub debug_log { return 1; } +sub calculate_context_lines { + my @lines = @_; + my $count = 0; + my $hunk_line = 0; + + foreach my $line (@lines) { + if ($line =~ /^${ansi_color_regex}(@@@* .+? @@@*)(.*)/) { + $hunk_line = $count; + } elsif ($hunk_line && $line =~ /^${ansi_color_regex}[+-]/) { + my $diff = $count - $hunk_line - 1; + #print "Hunk: $hunk_line, ChangedLine: $count ($diff context)\n"; + return $diff; + } + + $count++; + }; + + # If for some reason we can't figure it out, assume 3 + return 3; +} + # Borrowed from: https://www.perturb.org/display/1097_Perl_detect_if_a_module_is_installed_before_using_it.html sub AUTOLOAD { our $AUTOLOAD; # keep 'use strict' happy From 3642fce87a523a13518eb27b55370b690c817d66 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Tue, 8 Mar 2022 15:55:21 -0800 Subject: [PATCH 30/41] Output the average using floating point --- third_party/cli_bench/cli_bench.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/cli_bench/cli_bench.pl b/third_party/cli_bench/cli_bench.pl index 7c3aaee..e2e0214 100644 --- a/third_party/cli_bench/cli_bench.pl +++ b/third_party/cli_bench/cli_bench.pl @@ -59,7 +59,7 @@ @res = sort(@res); @res = splice(@res, $outlier, $num - $outlier * 2); -my $avg = int(average(@res)); +my $avg = sprintf("%.1f", average(@res)); if ($details) { show_details(@res); From 8ef749f4edf5ea8fcc666f526b528218bf3ea830 Mon Sep 17 00:00:00 2001 From: Vitaly Zdanevich Date: Wed, 15 Feb 2023 20:25:31 +0400 Subject: [PATCH 31/41] README: distros: add Gentoo (#456) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2d55448..f4115b0 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,11 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. +<<<<<<< HEAD `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/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian), and in the [Fedora COPR repository](https://copr.fedorainfracloud.org/coprs/kopfkrieg/diff-so-fancy/). +======= +`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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/7833a73834c5a4ffe060acd576bfdeeef2a9d5b8/app-misc/diff-so-fancy), [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian). +>>>>>>> f2e9408 (README: distros: add Gentoo (#456)) 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. From 63b4530d270fdb10abd83cdd6941b18e33955009 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Thu, 8 Jun 2023 15:03:10 -0700 Subject: [PATCH 32/41] README: Gentoo package link: fix from commit to master (#457) --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index f4115b0..07957ff 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -<<<<<<< HEAD -`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/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian), and in the [Fedora COPR repository](https://copr.fedorainfracloud.org/coprs/kopfkrieg/diff-so-fancy/). -======= `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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/7833a73834c5a4ffe060acd576bfdeeef2a9d5b8/app-misc/diff-so-fancy), [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian). ->>>>>>> f2e9408 (README: distros: add Gentoo (#456)) 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. From 8fede3b2c766682791dd77d83ef734352f063e44 Mon Sep 17 00:00:00 2001 From: mikaello <2505178+mikaello@users.noreply.github.com> Date: Mon, 27 Feb 2023 14:43:33 +0100 Subject: [PATCH 33/41] docs: fix url to Nix package --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07957ff..e1e1fc7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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), and as a package on [Nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-and-tools/diff-so-fancy/default.nix), [Fedora](https://packages.fedoraproject.org/pkgs/diff-so-fancy/diff-so-fancy/), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/7833a73834c5a4ffe060acd576bfdeeef2a9d5b8/app-misc/diff-so-fancy), [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), and 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 community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/master/app-misc/diff-so-fancy), [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' own repositories/issue trackers where applicable. From 006ede37b62c7b574710b823fae7750ea661c02f Mon Sep 17 00:00:00 2001 From: KopfKrieg Date: Sun, 23 Jan 2022 01:04:06 +0100 Subject: [PATCH 34/41] Added Fedora COPR repository to the installation section of the README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1e1fc7..c97f551 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Vanilla `git diff` vs `git` and `diff-so-fancy` 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. -`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), and 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 community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), [Gentoo Guru](https://github.com/gentoo/guru/tree/master/app-misc/diff-so-fancy), [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/git-and-tools/diff-so-fancy/default.nix), in the [Arch community repo](https://archlinux.org/packages/community/any/diff-so-fancy/), as [ppa:aos for Debian/Ubuntu Linux](https://github.com/aos/dsf-debian), and as [Fedora COPR repository](https://copr.fedorainfracloud.org/coprs/kopfkrieg/diff-so-fancy/). 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. From 32f5c1d36eff33c1268e4ea93781227942b224aa Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Thu, 8 Jun 2023 15:00:02 -0700 Subject: [PATCH 35/41] Potential fix for #469 --- test/bugs.bats | 6 ++++++ test/fixtures/ansi_reset_without_zero.diff | 5 +++++ 2 files changed, 11 insertions(+) create mode 100644 test/fixtures/ansi_reset_without_zero.diff diff --git a/test/bugs.bats b/test/bugs.bats index c209be7..460a989 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 leading zero (#469)" { + output=$( load_fixture "ansi_reset_without_zero" | $diff_so_fancy ) + run printf "%s" "$output" + assert_line --index 4 --partial 'Hello' +} diff --git a/test/fixtures/ansi_reset_without_zero.diff b/test/fixtures/ansi_reset_without_zero.diff new file mode 100644 index 0000000..d83b4f2 --- /dev/null +++ b/test/fixtures/ansi_reset_without_zero.diff @@ -0,0 +1,5 @@ +--- /tmp/baker/one.txt 2023-06-08 14:48:26.883146532 -0700 ++++ /tmp/baker/two.txt 2023-06-08 14:48:35.080137160 -0700 +@@ -1 +1 @@ +-Hello world ++Hello Jason From ee88b686460f0a037804644e99e16bf198c1a504 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Thu, 8 Jun 2023 15:19:14 -0700 Subject: [PATCH 36/41] Revert "Potential fix for #469" This reverts commit 32f5c1d36eff33c1268e4ea93781227942b224aa. --- test/bugs.bats | 6 ------ test/fixtures/ansi_reset_without_zero.diff | 5 ----- 2 files changed, 11 deletions(-) delete mode 100644 test/fixtures/ansi_reset_without_zero.diff diff --git a/test/bugs.bats b/test/bugs.bats index 460a989..c209be7 100644 --- a/test/bugs.bats +++ b/test/bugs.bats @@ -75,9 +75,3 @@ teardown_file() { run printf "%s" "$output" assert_line --index 3 --partial "@ height" } - -@test "ANSI reset without leading zero (#469)" { - output=$( load_fixture "ansi_reset_without_zero" | $diff_so_fancy ) - run printf "%s" "$output" - assert_line --index 4 --partial 'Hello' -} diff --git a/test/fixtures/ansi_reset_without_zero.diff b/test/fixtures/ansi_reset_without_zero.diff deleted file mode 100644 index d83b4f2..0000000 --- a/test/fixtures/ansi_reset_without_zero.diff +++ /dev/null @@ -1,5 +0,0 @@ ---- /tmp/baker/one.txt 2023-06-08 14:48:26.883146532 -0700 -+++ /tmp/baker/two.txt 2023-06-08 14:48:35.080137160 -0700 -@@ -1 +1 @@ --Hello world -+Hello Jason From 0b39dfb145b9d17ef6f4d63f7f5ade7929e6a4b1 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Fri, 9 Jun 2023 10:32:02 -0700 Subject: [PATCH 37/41] Update `report-bug.sh` for #461 --- report-bug.sh | 106 ++++++++++++++++++++++++---------------------- reporting-bugs.md | 6 +-- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/report-bug.sh b/report-bug.sh index 8f9fd8d..7419fbd 100755 --- a/report-bug.sh +++ b/report-bug.sh @@ -1,60 +1,66 @@ #!/bin/bash clipboard() { - local copy_cmd - if [ -n "$PBCOPY_SERVER" ]; then - local body="" # buffer - body=$(cat) - # while IFS= read -r buffer; do - # body="$body$buffer\n"; - # done - curl "$PBCOPY_SERVER" --data-urlencode body="$body" >/dev/null 2>&1 - return $? - fi - if type putclip >/dev/null 2>&1; then - copy_cmd="putclip" - elif [ -e /dev/clipboard ];then - cat > /dev/clipboard - return 0 - elif type clip >/dev/null 2>&1; then - if [[ $LANG = UTF-8 ]]; then - copy_cmd="iconv -f utf-8 -t shift_jis | clip" - else - copy_cmd=clip - fi - # copy_cmd=clip - elif command -v pbcopy >/dev/null 2>&1; then - copy_cmd="pbcopy" - elif command -v xclip >/dev/null 2>&1; then - # copy_cmd="xclip -i -selection clipboard" - copy_cmd="xclip" - elif command -v xsel >/dev/null 2>&1 ; then - local copy_cmd="xsel -b" - fi - if [ -n "$copy_cmd" ] ;then - eval "$copy_cmd" - else - echo "clipboard is unavailable" 1>&2 - fi + local copy_cmd + + if [ -n "$PBCOPY_SERVER" ]; then + local body="" # buffer + body=$(cat) + # while IFS= read -r buffer; do + # body="$body$buffer\n"; + # done + curl "$PBCOPY_SERVER" --data-urlencode body="$body" >/dev/null 2>&1 + return $? + fi + + if type putclip >/dev/null 2>&1; then + copy_cmd="putclip" + elif [ -e /dev/clipboard ];then + cat > /dev/clipboard + return 0 + elif type clip >/dev/null 2>&1; then + if [[ $LANG = UTF-8 ]]; then + copy_cmd="iconv -f utf-8 -t shift_jis | clip" + else + copy_cmd=clip + fi + # copy_cmd=clip + elif command -v pbcopy >/dev/null 2>&1; then + copy_cmd="pbcopy" + elif command -v xclip >/dev/null 2>&1; then + # copy_cmd="xclip -i -selection clipboard" + copy_cmd="xclip" + elif command -v xsel >/dev/null 2>&1 ; then + local copy_cmd="xsel -b" + fi + + if [ -n "$copy_cmd" ] ;then + eval "$copy_cmd" + else + echo "clipboard is unavailable" 1>&2 + fi } -file=${2:-diff.txt} +if [ $# -eq 0 ]; then + echo "Usage: $0 'git diff HEAD..HEAD^'" + exit 7 +fi -{ - echo "$1" - eval "$1" - echo "" - echo "" - echo "" +file=${2:-dsf-bug-report.txt} - echo "$1 --color" - eval "$1 --color" +{ + echo "$1" + eval "$1" + echo "" + echo "" + echo "" - echo "git config pager.diff" - eval "git config pager.diff" + echo "$1 --color" + eval "$1 --color" - echo "git config pager.show" - eval "git config pager.show" -} > "$file" + echo "git config --list | grep pager" + eval "git config --list | grep pager" +} | base64 > "$file" -base64 < "$file" | clipboard +echo "Wrote file: $file" +echo "Please open a new issue on Github and attach it" diff --git a/reporting-bugs.md b/reporting-bugs.md index 109fd19..eb0989d 100644 --- a/reporting-bugs.md +++ b/reporting-bugs.md @@ -10,10 +10,6 @@ You can use [report-bug.sh](./report-bug.sh) we provide ```sh ./report-bug.sh 'git diff HEAD..HEAD^' - -# or - -curl https://raw.githubusercontent.com/so-fancy/diff-so-fancy/master/report-bug.sh | bash -s 'git diff HEAD..HEAD^' 'diff.txt' ``` -Grab the output file and attach to the GitHub issue you create. A base64 version is also copied to your clipboard so you can paste to the issue. +Attach the output file to the GitHub issue you create. From 9ffea48cc4eadedd9d280c11fc8919bf2aef9e41 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Fri, 9 Jun 2023 10:49:10 -0700 Subject: [PATCH 38/41] Don't error out if git is not installed (#429) --- diff-so-fancy | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index e440fda..516378f 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -454,7 +454,7 @@ sub boolean { # Get the git config sub git_config_raw { - my $cmd = "git config --list"; + my $cmd = "git config --list 2>&1"; my @out = `$cmd`; return \@out; @@ -1030,11 +1030,17 @@ sub get_terminal_width { sub show_debug_info { my @less = get_less_charset(); - my $git_ver = trim(`git --version`); + my $git_ver = trim(`git --version 2>&1`); $git_ver =~ s/[^\d.]//g; + if ($git_ver !~ /git/) { + $git_ver = "Unknown"; + } else { + $git_ver = "v" . $git_ver; + } + print "Diff-so-fancy : v$VERSION\n"; - print "Git : v$git_ver\n"; + print "Git : $git_ver\n"; print "Perl : $^V\n"; print "\n"; From 8949ad9fc8bae393c9403531bf444dbccfc79142 Mon Sep 17 00:00:00 2001 From: "Chris. Webster" Date: Fri, 9 Jun 2023 11:01:30 -0700 Subject: [PATCH 39/41] fix and maint: match most git supported color settings (#453) * maint: set ansi colors in common routine Setting foreground and background colors is now using the same code. Signed-off-by: Chris. Webster * fix: ignore negative color attributes with tests The colors in the git config may have attributes and negative versions of them (no/no- prefix). The negative versions will no longer cause a false positive checking for the attribute. A new test file is specifically for testing the settings of the ansi codes and the possible settings in the git config. Signed-off-by: Chris. Webster * fix: support git config colors normal and default Normal is a placeholder and will be ignored. Default will generate ansi codes for the default foreground or background color. Git validates the config so a bright prefix on these values would not be allowed. They are added to the hash to keep the code simple. Signed-off-by: Chris. Webster * fix: support #rgb colors in git config Git supports diff colors in #rrggbb notation. diff-so-fancy now supports them as well. Signed-off-by: Chris. Webster --------- Signed-off-by: Chris. Webster --- diff-so-fancy | 70 +++++++++--------- test/git-config.bats | 171 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+), 37 deletions(-) create mode 100644 test/git-config.bats diff --git a/diff-so-fancy b/diff-so-fancy index 516378f..34c9753 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -904,6 +904,8 @@ sub git_ansi_color { 'magenta' => 5, 'cyan' => 6, 'white' => 7, + 'default' => 9, # pseudo color (39/49 = set default) + 'normal' => -1, # placeholder color to be ignored }; # Bright colors are just offsets from the "regular" color @@ -913,68 +915,62 @@ sub git_ansi_color { my @ansi_part = (); - if (grep { /bold/ } @parts) { + if (grep { /^bold$/ } @parts) { push(@ansi_part, "1"); } - if (grep { /dim/ } @parts) { + if (grep { /^dim$/ } @parts) { push(@ansi_part, "2"); } - if (grep { /ul/ } @parts) { + if (grep { /^ul$/ } @parts) { push(@ansi_part, "4"); } - if (grep { /reverse/ } @parts) { + if (grep { /^reverse$/ } @parts) { push(@ansi_part, "7"); } # Remove parts that aren't colors - @parts = grep { exists $colors->{$_} || is_numeric($_) } @parts; + @parts = grep { exists $colors->{$_} || is_numeric($_) || /^\#/ } @parts; my $fg = $parts[0] // ""; my $bg = $parts[1] // ""; + set_ansi_color( $fg, 0, \@ansi_part, $colors ) if $fg; + set_ansi_color( $bg, 10, \@ansi_part, $colors ) if $bg; + ############################################# - # It's an numeric value, so it's an 8 bit color - if (is_numeric($fg)) { - if ($fg < 8) { - push(@ansi_part, $fg + 30); - } elsif ($fg < 16) { - push(@ansi_part, $fg + 82); - } else { - push(@ansi_part, "38;5;$fg"); - } - # It's a simple 16 color OG ansi - } elsif ($fg) { - my $color_num = ($colors->{$fg} // 0) + 30; - push(@ansi_part, $color_num); - } + my $ansi_str = join(";", @ansi_part); + my $ret = "\e[" . $ansi_str . "m"; - ############################################# + return $ret; +} - # It's an numeric value, so it's an 8 bit color - if (is_numeric($bg)) { - if ($bg < 8) { - push(@ansi_part, $bg + 40); - } elsif ($bg < 16) { - push(@ansi_part, $bg + 92); +sub set_ansi_color { + my ($color, $increment, $ansi_part, $colors) = @_; + my $base_code = 30 + $increment; + my $base8_code = 38 + $increment; + my $ext_code = 82 + $increment; + + if (is_numeric($color)) { + if ($color < 8) { + push(@$ansi_part, $color + $base_code); + } elsif ($color < 16) { + push(@$ansi_part, $color + $ext_code); } else { - push(@ansi_part, "48;5;$bg"); + push(@$ansi_part, "$base8_code;5;$color"); } + # It's a full rgb code + } elsif ($color =~ /^#/) { + my ($rgbr, $rgbg, $rgbb) = $color =~ /.(..)(..)(..)/; + push(@$ansi_part, "$base8_code;2;" . hex($rgbr) . ";" . hex($rgbg) . ";" . hex($rgbb)); # It's a simple 16 color OG ansi - } elsif ($bg) { - my $color_num = ($colors->{$bg} // 0) + 40; - push(@ansi_part, $color_num); + } elsif ($color ne "normal") { + my $color_num = $colors->{$color} + $base_code; + push(@$ansi_part, $color_num); } - - ############################################# - - my $ansi_str = join(";", @ansi_part); - my $ret = "\e[" . $ansi_str . "m"; - - return $ret; } sub is_numeric { diff --git a/test/git-config.bats b/test/git-config.bats new file mode 100644 index 0000000..462ee74 --- /dev/null +++ b/test/git-config.bats @@ -0,0 +1,171 @@ +#!/usr/bin/env bats + +# Used by both `setup_file` and `setup`, which are special bats callbacks. +__load_imports__() { + load 'test_helper/bats-support/load' + load 'test_helper/bats-assert/load' + load 'test_helper/util' +} + +# ansi related values +escape=$'\e' +ansi_bold=1 +ansi_dim=2 +ansi_ul=4 +ansi_reverse=7 + +# hash of colors +declare -Ag ansi_colors=( + [black]='0' + [red]='1' + [green]='2' + [yellow]='3' + [blue]='4' + [magenta]='5' + [cyan]='6' + [white]='7' + [default]='9' +) + +# get a foreground or background color code +ansi_color() { + color=$1 + incr=$2 + base_code=$((30+$incr)) + + # handle bright prefix + if [[ "${1}" =~ (bright)(.*) ]] + then + color=${BASH_REMATCH[2]} + base_code=$((90+$incr)) + fi + code=$(($base_code+${ansi_colors[$color]})) + echo "$code" +} + +# get a foreground color code +fg_color() { + ansi_color $1 0 +} + +# get a background color code +bg_color() { + ansi_color $1 10 +} + +# get rgb color codes from hex +rgb_color() { + incr=$2 + base_code=$((38+$incr)) + [[ $1 =~ ^.(..)(..)(..)$ ]] + rgb1="${BASH_REMATCH[1]}" + rgb2="${BASH_REMATCH[2]}" + rgb3="${BASH_REMATCH[3]}" + echo "${base_code};2;$(( 16#${rgb1} ));$(( 16#${rgb2} ));$(( 16#${rgb3} ))" +} + +# get a foreground color code +fg_rgb_color() { + rgb_color $1 0 +} + +# get a background color code +bg_rgb_color() { + rgb_color $1 10 +} + +# build config using passed in values +setup_dsf_git_config() { + GIT_CONFIG="$(dsf_test_git_config)" || return $? + cat > "${GIT_CONFIG}" < Date: Fri, 9 Jun 2023 11:02:51 -0700 Subject: [PATCH 40/41] We don't need to store the fatpacked version here anymore --- third_party/build_fatpack/diff-so-fancy | 1442 ----------------------- 1 file changed, 1442 deletions(-) delete mode 100755 third_party/build_fatpack/diff-so-fancy diff --git a/third_party/build_fatpack/diff-so-fancy b/third_party/build_fatpack/diff-so-fancy deleted file mode 100755 index 2e165ad..0000000 --- a/third_party/build_fatpack/diff-so-fancy +++ /dev/null @@ -1,1442 +0,0 @@ -#!/usr/bin/env perl - -# This chunk of stuff was generated by App::FatPacker. To find the original -# file's code, look for the end of this BEGIN block or the string 'FATPACK' -BEGIN { -my %fatpacked; - -$fatpacked{"DiffHighlight.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'DIFFHIGHLIGHT'; - package DiffHighlight; - - use 5.008; - use warnings FATAL => 'all'; - use strict; - - # Use the correct value for both UNIX and Windows (/dev/null vs nul) - use File::Spec; - - my $NULL = File::Spec->devnull(); - - # Highlight by reversing foreground and background. You could do - # other things like bold or underline if you prefer. - our @OLD_HIGHLIGHT = ( - undef, - "\e[7m", - "\e[27m", - ); - our @NEW_HIGHLIGHT = ( - $OLD_HIGHLIGHT[0], - $OLD_HIGHLIGHT[1], - $OLD_HIGHLIGHT[2], - ); - - - - my $RESET = "\x1b[m"; - my $COLOR = qr/\x1b\[[0-9;]*m/; - my $BORING = qr/$COLOR|\s/; - - my @removed; - my @added; - my $in_hunk; - my $graph_indent = 0; - - our $line_cb = sub { print @_ }; - our $flush_cb = sub { local $| = 1 }; - - # Count the visible width of a string, excluding any terminal color sequences. - sub visible_width { - local $_ = shift; - my $ret = 0; - while (length) { - if (s/^$COLOR//) { - # skip colors - } elsif (s/^.//) { - $ret++; - } - } - return $ret; - } - - # Return a substring of $str, omitting $len visible characters from the - # beginning, where terminal color sequences do not count as visible. - sub visible_substr { - my ($str, $len) = @_; - while ($len > 0) { - if ($str =~ s/^$COLOR//) { - next - } - $str =~ s/^.//; - $len--; - } - return $str; - } - - sub handle_line { - my $orig = shift; - local $_ = $orig; - - # match a graph line that begins a commit - if (/^(?:$COLOR?\|$COLOR?[ ])* # zero or more leading "|" with space - $COLOR?\*$COLOR?[ ] # a "*" with its trailing space - (?:$COLOR?\|$COLOR?[ ])* # zero or more trailing "|" - [ ]* # trailing whitespace for merges - /x) { - my $graph_prefix = $&; - - # We must flush before setting graph indent, since the - # new commit may be indented differently from what we - # queued. - flush(); - $graph_indent = visible_width($graph_prefix); - - } elsif ($graph_indent) { - if (length($_) < $graph_indent) { - $graph_indent = 0; - } else { - $_ = visible_substr($_, $graph_indent); - } - } - - if (!$in_hunk) { - $line_cb->($orig); - $in_hunk = /^$COLOR*\@\@ /; - } - elsif (/^$COLOR*-/) { - push @removed, $orig; - } - elsif (/^$COLOR*\+/) { - push @added, $orig; - } - else { - flush(); - $line_cb->($orig); - $in_hunk = /^$COLOR*[\@ ]/; - } - - # Most of the time there is enough output to keep things streaming, - # but for something like "git log -Sfoo", you can get one early - # commit and then many seconds of nothing. We want to show - # that one commit as soon as possible. - # - # Since we can receive arbitrary input, there's no optimal - # place to flush. Flushing on a blank line is a heuristic that - # happens to match git-log output. - if (!length) { - $flush_cb->(); - } - } - - sub flush { - # Flush any queued hunk (this can happen when there is no trailing - # context in the final diff of the input). - show_hunk(\@removed, \@added); - @removed = (); - @added = (); - } - - sub highlight_stdin { - while () { - handle_line($_); - } - flush(); - } - - # Ideally we would feed the default as a human-readable color to - # git-config as the fallback value. But diff-highlight does - # not otherwise depend on git at all, and there are reports - # of it being used in other settings. Let's handle our own - # fallback, which means we will work even if git can't be run. - sub color_config { - my ($key, $default) = @_; - - # Removing the redirect speeds up execution by about 12ms - #my $s = `git config --get-color $key 2>$NULL`; - my $s = `git config --get-color $key`; - - return length($s) ? $s : $default; - } - - sub show_hunk { - my ($a, $b) = @_; - - # If one side is empty, then there is nothing to compare or highlight. - if (!@$a || !@$b) { - $line_cb->(@$a, @$b); - return; - } - - # If we have mismatched numbers of lines on each side, we could try to - # be clever and match up similar lines. But for now we are simple and - # stupid, and only handle multi-line hunks that remove and add the same - # number of lines. - if (@$a != @$b) { - $line_cb->(@$a, @$b); - return; - } - - my @queue; - for (my $i = 0; $i < @$a; $i++) { - my ($rm, $add) = highlight_pair($a->[$i], $b->[$i]); - $line_cb->($rm); - push @queue, $add; - } - $line_cb->(@queue); - } - - sub highlight_pair { - my @a = split_line(shift); - my @b = split_line(shift); - - # Find common prefix, taking care to skip any ansi - # color codes. - my $seen_plusminus; - my ($pa, $pb) = (0, 0); - while ($pa < @a && $pb < @b) { - if ($a[$pa] =~ /$COLOR/) { - $pa++; - } - elsif ($b[$pb] =~ /$COLOR/) { - $pb++; - } - elsif ($a[$pa] eq $b[$pb]) { - $pa++; - $pb++; - } - elsif (!$seen_plusminus && $a[$pa] eq '-' && $b[$pb] eq '+') { - $seen_plusminus = 1; - $pa++; - $pb++; - } - else { - last; - } - } - - # Find common suffix, ignoring colors. - my ($sa, $sb) = ($#a, $#b); - while ($sa >= $pa && $sb >= $pb) { - if ($a[$sa] =~ /$COLOR/) { - $sa--; - } - elsif ($b[$sb] =~ /$COLOR/) { - $sb--; - } - elsif ($a[$sa] eq $b[$sb]) { - $sa--; - $sb--; - } - else { - last; - } - } - - if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) { - return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT), - highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT); - } - else { - return join('', @a), - join('', @b); - } - } - - # we split either by $COLOR or by character. This has the side effect of - # leaving in graph cruft. It works because the graph cruft does not contain "-" - # or "+" - sub split_line { - local $_ = shift; - return utf8::decode($_) ? - map { utf8::encode($_); $_ } - map { /$COLOR/ ? $_ : (split //) } - split /($COLOR+)/ : - map { /$COLOR/ ? $_ : (split //) } - split /($COLOR+)/; - } - - sub highlight_line { - my ($line, $prefix, $suffix, $theme) = @_; - - my $start = join('', @{$line}[0..($prefix-1)]); - my $mid = join('', @{$line}[$prefix..$suffix]); - my $end = join('', @{$line}[($suffix+1)..$#$line]); - - # If we have a "normal" color specified, then take over the whole line. - # Otherwise, we try to just manipulate the highlighted bits. - if (defined $theme->[0]) { - s/$COLOR//g for ($start, $mid, $end); - chomp $end; - return join('', - $theme->[0], $start, $RESET, - $theme->[1], $mid, $RESET, - $theme->[0], $end, $RESET, - "\n" - ); - } else { - return join('', - $start, - $theme->[1], $mid, $theme->[2], - $end - ); - } - } - - # Pairs are interesting to highlight only if we are going to end up - # highlighting a subset (i.e., not the whole line). Otherwise, the highlighting - # is just useless noise. We can detect this by finding either a matching prefix - # or suffix (disregarding boring bits like whitespace and colorization). - sub is_pair_interesting { - my ($a, $pa, $sa, $b, $pb, $sb) = @_; - my $prefix_a = join('', @$a[0..($pa-1)]); - my $prefix_b = join('', @$b[0..($pb-1)]); - my $suffix_a = join('', @$a[($sa+1)..$#$a]); - my $suffix_b = join('', @$b[($sb+1)..$#$b]); - - return visible_substr($prefix_a, $graph_indent) !~ /^$COLOR*-$BORING*$/ || - visible_substr($prefix_b, $graph_indent) !~ /^$COLOR*\+$BORING*$/ || - $suffix_a !~ /^$BORING*$/ || - $suffix_b !~ /^$BORING*$/; - } -DIFFHIGHLIGHT - -s/^ //mg for values %fatpacked; - -my $class = 'FatPacked::'.(0+\%fatpacked); -no strict 'refs'; -*{"${class}::files"} = sub { keys %{$_[0]} }; - -if ($] < 5.008) { - *{"${class}::INC"} = sub { - if (my $fat = $_[0]{$_[1]}) { - my $pos = 0; - my $last = length $fat; - return (sub { - return 0 if $pos == $last; - my $next = (1 + index $fat, "\n", $pos) || $last; - $_ .= substr $fat, $pos, $next - $pos; - $pos = $next; - return 1; - }); - } - }; -} - -else { - *{"${class}::INC"} = sub { - if (my $fat = $_[0]{$_[1]}) { - open my $fh, '<', \$fat - or die "FatPacker error loading $_[1] (could be a perl installation issue?)"; - return $fh; - } - return; - }; -} - -unshift @INC, bless \%fatpacked, $class; - } # END OF FATPACK CODE - - -my $VERSION = "1.4.2"; - -################################################################################# - -use v5.010; # Require Perl 5.10 for 'state' variables -use warnings FATAL => 'all'; -use strict; - -use File::Spec; # For catdir -use File::Basename; # For dirname -use Cwd qw(abs_path); # For realpath() -use lib dirname(abs_path(File::Spec->catdir($0))) . "/lib"; # Add the local lib/ to @INC -use DiffHighlight; - -my $remove_file_add_header = 1; -my $remove_file_delete_header = 1; -my $clean_permission_changes = 1; -my $patch_mode = 0; -my $manually_color_lines = 0; # Usually git/hg colorizes the lines, but for raw patches we use this -my $change_hunk_indicators = git_config_boolean("diff-so-fancy.changeHunkIndicators","true"); -my $strip_leading_indicators = git_config_boolean("diff-so-fancy.stripLeadingSymbols","true"); -my $mark_empty_lines = git_config_boolean("diff-so-fancy.markEmptyLines","true"); -my $use_unicode_dash_for_ruler = git_config_boolean("diff-so-fancy.useUnicodeRuler","true"); -my $ruler_width = git_config("diff-so-fancy.rulerWidth", undef); -my $git_strip_prefix = git_config_boolean("diff.noprefix","false"); -my $has_stdin = has_stdin(); - -my $ansi_color_regex = qr/(\e\[([0-9]{1,3}(;[0-9]{1,3}){0,10})[mK])?/; -my $reset_color = color("reset"); -my $bold = color("bold"); -my $meta_color = ""; - -# Set the diff highlight colors from the config -init_diff_highlight_colors(); - -my ($file_1,$file_2); -my $args = argv(); # Hashref of all the ARGV stuff -my $last_file_seen = ""; -my $last_file_mode = ""; -my $i = 0; -my $in_hunk = 0; -my $columns_to_remove = 0; -my $is_mercurial = 0; -my $color_forced = 0; # Has the color been forced on/off - -# 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}) { - $manually_color_lines = 1; - $color_forced = 1; -} elsif ($args->{color_off}) { - $manually_color_lines = 0; - $color_forced = 1; -} - -if ($args->{debug}) { - show_debug_info(); - exit(); -} - -# `git add --patch` requires our output to match the number of lines from the -# input. So, when patch mode is active, we print out empty lines to pad our -# output to match any lines we've consumed. -if ($args->{patch}) { - $patch_mode = 1; -} - -# We only process ARGV if we don't have STDIN -if (!$has_stdin) { - if ($args->{v} || $args->{version}) { - die(version()); - } elsif ($args->{'set-defaults'}) { - my $ok = set_defaults(); - exit; - } elsif ($args->{colors}) { - # We print this to STDOUT so we can redirect to bash to auto-set the colors - print get_default_colors(); - exit; - } elsif (!%$args || $args->{help} || $args->{h}) { - my $first = check_first_run(); - - if (!$first) { - die(usage()); - } - } else { - die("Missing input on STDIN\n"); - } -} - -################################################################################# -################################################################################# - -# Check to see if were using default settings -check_first_run(); - -# The logic here is that we run all the lines through DiffHighlight first. This -# highlights all the intra-word changes. Then we take those lines and send them -# to do_dsf_stuff() to convert the diff to human readable d-s-f output and add -# appropriate fanciness - -my @lines; -local $DiffHighlight::line_cb = sub { - push(@lines,@_); - - my $last_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))/)) { - do_dsf_stuff(\@lines); - @lines = (); - } -}; - -my $line_count = 0; -while (my $line = ) { - # If the very first line of the diff doesn't start with ANSI color we're assuming - # it's a raw patch file, and we have to color the added/removed lines ourself - if (!$color_forced && $line_count == 0 && starts_with_ansi($line)) { - $manually_color_lines = 1; - } - - my $ok = DiffHighlight::handle_line($line); - $line_count++; -} - -# If we're mid hunk above process anything still pending -DiffHighlight::flush(); -do_dsf_stuff(\@lines); - -################################################################################# -################################################################################# - -sub do_dsf_stuff { - my $input = shift(); - - #print STDERR "START -------------------------------------------------\n"; - #print STDERR join("",@$input); - #print STDERR "END ---------------------------------------------------\n"; - - while (my $line = shift(@$input)) { - ###################################################### - # Pre-process the line before we do any other markup # - ###################################################### - - # If the first line of the input is a blank line, skip that - if ($i == 0 && $line =~ /^\s*$/) { - next; - } - - ###################### - # End pre-processing # - ###################### - - ####################################################################### - - #################################################################### - # Look for git index and replace it horizontal line (header later) # - #################################################################### - if ($line =~ /^${ansi_color_regex}index /) { - # Print the line color and then the actual line - $meta_color = $1 || get_config_color("meta"); - - # Get the next line without incrementing counter while loop - my $next = $input->[0] || ""; - my ($file_1,$file_2); - - # The line immediately after the "index" line should be the --- file line - # If it's not it's an empty file add/delete - if ($next !~ /^$ansi_color_regex(---|Binary files)/) { - - # We fake out the file names since it's a raw add/delete - if ($last_file_mode eq "add") { - $file_1 = "/dev/null"; - $file_2 = $last_file_seen; - } elsif ($last_file_mode eq "delete") { - $file_1 = $last_file_seen; - $file_2 = "/dev/null"; - } - } - - if ($file_1 && $file_2) { - print horizontal_rule($meta_color); - print $meta_color . file_change_string($file_1,$file_2) . "\n"; - print horizontal_rule($meta_color); - } - ######################### - # Look for the filename # - ######################### - # $4 $5 - } elsif ($line =~ /^${ansi_color_regex}diff (-r|--git|--cc) (.*?)(\e| b\/|$)/) { - - # Mercurial looks like: diff -r 82e55d328c8c hello.c - if ($4 eq "-r") { - $is_mercurial = 1; - $meta_color = get_config_color("meta"); - # Git looks like: diff --git a/diff-so-fancy b/diff-so-fancy - } else { - $last_file_seen = $5; - } - - $last_file_seen =~ s|^\w/||; # Remove a/ (and handle diff.mnemonicPrefix). - $in_hunk = 0; - if ($patch_mode) { - # we are consuming one line, and the debt must be paid - print "\n"; - } - ######################################## - # Find the first file: --- a/README.md # - ######################################## - } elsif (!$in_hunk && $line =~ /^$ansi_color_regex--- (\w\/)?(.+?)(\e|\t|$)/) { - $meta_color = get_config_color("meta"); - - if ($git_strip_prefix) { - my $file_dir = $4 || ""; - $file_1 = $file_dir . $5; - } else { - $file_1 = $5; - } - - # Find the second file on the next line: +++ b/README.md - my $next = shift(@$input); - $next =~ /^$ansi_color_regex\+\+\+ (\w\/)?(.+?)(\e|\t|$)/; - if ($1) { - print $1; # Print out whatever color we're using - } - if ($git_strip_prefix) { - my $file_dir = $4 || ""; - $file_2 = $file_dir . $5; - } else { - $file_2 = $5; - } - - if ($file_2 ne "/dev/null") { - $last_file_seen = $file_2; - } - - # Print out the top horizontal line of the header - print $reset_color; - print horizontal_rule($meta_color); - - # Mercurial coloring is slightly different so we need to hard reset colors - if ($is_mercurial) { - print $reset_color; - } - - print $meta_color; - print file_change_string($file_1,$file_2) . "\n"; - - # Print out the bottom horizontal line of the header - print horizontal_rule($meta_color); - ######################################## - # Check for "@@ -3,41 +3,63 @@" syntax # - ######################################## - } elsif (!$change_hunk_indicators && $line =~ /^${ansi_color_regex}(@@@* .+? @@@*)(.*)/) { - $in_hunk = 1; - - print $line; - } elsif ($change_hunk_indicators && $line =~ /^${ansi_color_regex}(@@@* .+? @@@*)(.*)/) { - $in_hunk = 1; - - my $hunk_header = $4; - my $remain = bleach_text($5); - - # The number of colums to remove (1 or 2) is based on how many commas in the hunk header - $columns_to_remove = (char_count(",",$hunk_header)) - 1; - # On single line removes there is NO comma in the hunk so we force one - if ($columns_to_remove <= 0) { - $columns_to_remove = 1; - } - - if ($1) { - print $1; # Print out whatever color we're using - } - - my ($orig_offset, $orig_count, $new_offset, $new_count) = parse_hunk_header($hunk_header); - #$last_file_seen = basename($last_file_seen); - - # Figure out the start line - my $start_line = start_line_calc($new_offset,$new_count); - - # Last function has it's own color - my $last_function_color = ""; - if ($remain) { - $last_function_color = get_config_color("last_function"); - } - - # Check to see if we have the color for the fragment from git - if ($5 =~ /\e\[\d/) { - #print "Has ANSI color for fragment\n"; - } else { - # We don't have the ANSI sequence so we shell out to get it - #print "No ANSI color for fragment\n"; - my $frag_color = get_config_color("fragment"); - print $frag_color; - } - - print "@ $last_file_seen:$start_line \@${bold}${last_function_color}${remain}${reset_color}\n"; - ################################### - # Remove any new file permissions # - ################################### - } elsif ($remove_file_add_header && $line =~ /^${ansi_color_regex}.*new file mode/) { - # Don't print the line (i.e. remove it from the output); - $last_file_mode = "add"; - if ($patch_mode) { - print "\n"; - } - ###################################### - # Remove any delete file permissions # - ###################################### - } elsif ($remove_file_delete_header && $line =~ /^${ansi_color_regex}deleted file mode/) { - # Don't print the line (i.e. remove it from the output); - $last_file_mode = "delete"; - if ($patch_mode) { - print "\n"; - } - ################################ - # Look for binary file changes # - ################################ - } elsif ($line =~ /^Binary files (\w\/)?(.+?) and (\w\/)?(.+?) differ/) { - my $change = file_change_string($2,$4); - print horizontal_rule($meta_color); - print "$meta_color$change (binary)\n"; - print horizontal_rule($meta_color); - ##################################################### - # Check if we're changing the permissions of a file # - ##################################################### - } elsif ($clean_permission_changes && $line =~ /^${ansi_color_regex}old mode (\d+)/) { - my ($old_mode) = $4; - my $next = shift(@$input); - - if ($1) { - print $1; # Print out whatever color we're using - } - - my ($new_mode) = $next =~ m/new mode (\d+)/; - - if ($patch_mode) { - print "\n"; - } - print "$last_file_seen changed file mode from $old_mode to $new_mode\n"; - - ############### - # File rename # - ############### - } elsif ($line =~ /^${ansi_color_regex}similarity index (\d+)%/) { - my $simil = $4; - - # If it's a move with content change we ignore this and the next two lines - if ($simil != 100) { - shift(@$input); - shift(@$input); - next; - } - - my $next = shift(@$input); - my ($file1) = $next =~ /rename from (.+?)(\e|\t|$)/; - - $next = shift(@$input); - my ($file2) = $next =~ /rename to (.+?)(\e|\t|$)/; - - if ($file1 && $file2) { - # We may not have extracted this yet, so we pull from the config if not - $meta_color = get_config_color("meta"); - - my $change = file_change_string($file1,$file2); - - print horizontal_rule($meta_color); - print $meta_color . $change . "\n"; - print horizontal_rule($meta_color); - } - - $i += 3; # We've consumed three lines - next; - ##################################### - # Just a regular line, print it out # - ##################################### - } else { - # Mark empty line with a red/green box indicating addition/removal - if ($mark_empty_lines) { - $line = mark_empty_line($line); - } - - # Remove the correct number of leading " " or "+" or "-" - if ($strip_leading_indicators) { - $line = strip_leading_indicators($line,$columns_to_remove); - } - print $line; - } - - $i++; - } -} - -###################################################################################################### -# End regular code, begin functions -###################################################################################################### - -# Courtesy of github.com/git/git/blob/ab5d01a/git-add--interactive.perl#L798-L805 -sub parse_hunk_header { - my ($line) = @_; - my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) = $line =~ /^\@\@+(?: -(\d+)(?:,(\d+))?)+ \+(\d+)(?:,(\d+))? \@\@+/; - $o_cnt = 1 unless defined $o_cnt; - $n_cnt = 1 unless defined $n_cnt; - return ($o_ofs, $o_cnt, $n_ofs, $n_cnt); -} - -# Mark the first char of an empty line -sub mark_empty_line { - my $line = shift(); - - my $reset_color = "\e\\[0?m"; - my $reset_escape = "\e\[m"; - my $invert_color = "\e\[7m"; - my $add_color = $DiffHighlight::NEW_HIGHLIGHT[1]; - my $del_color = $DiffHighlight::OLD_HIGHLIGHT[1]; - - # This captures lines that do not have any ANSI in them (raw vanilla diff) - if ($line eq "+\n") { - $line = $invert_color . $add_color . " " . color('reset') . "\n"; - # This captures lines that do not have any ANSI in them (raw vanilla diff) - } elsif ($line eq "-\n") { - $line = $invert_color . $del_color . " " . color('reset') . "\n"; - # This handles everything else - } else { - $line =~ s/^($ansi_color_regex)[+-]$reset_color\s*$/$invert_color$1 $reset_escape\n/; - } - - return $line; -} - -# String to boolean -sub boolean { - my $str = shift(); - $str = trim($str); - - if ($str eq "" || $str =~ /^(no|false|0)$/i) { - return 0; - } else { - return 1; - } -} - -# Get the git config -sub git_config_raw { - my $cmd = "git config --list"; - my @out = `$cmd`; - - return \@out; -} - -# Memoize fetching a textual item from the git config -sub git_config { - my $search_key = lc($_[0] || ""); - my $default_value = lc($_[1] || ""); - - state $raw = {}; - if (%$raw && $search_key) { - return $raw->{$search_key} || $default_value; - } - - if ($args->{debug}) { - print "Parsing git config\n"; - } - - my $out = git_config_raw(); - - foreach my $line (@$out) { - if ($line =~ /=/) { - my ($key,$value) = split("=",$line,2); - $value =~ s/\s+$//; - $raw->{$key} = $value; - } - } - - # If we're given a search key return that, else return the hash - if ($search_key) { - return $raw->{$search_key} || $default_value; - } else { - return $raw; - } -} - -# Fetch a boolean item from the git config -sub git_config_boolean { - my $search_key = lc($_[0] || ""); - my $default_value = lc($_[1] || 0); # Default to false - - # If we're in a unit test, use the default (don't read the users config) - if (in_unit_test()) { - return boolean($default_value); - } - - my $result = git_config($search_key,$default_value); - my $ret = boolean($result); - - return $ret; -} - -# Check if we're inside of BATS -sub in_unit_test { - if ($ENV{BATS_CWD}) { - return 1; - } else { - return 0; - } -} - -sub get_less_charset { - my @less_char_vars = ("LESSCHARSET", "LESSCHARDEF", "LC_ALL", "LC_CTYPE", "LANG"); - foreach my $key (@less_char_vars) { - my $val = $ENV{$key}; - - if (defined $val) { - return ($key, $val); - } - } - - return (); -} - -sub should_print_unicode { - if (-t STDOUT) { - # Always print unicode chars if we're not piping stuff, e.g. to less(1) - return 1; - } - - # Otherwise, assume we're piping to less(1) - my ($less_env_var, $less_charset) = get_less_charset(); - if ($less_charset && $less_charset =~ /utf-?8/i) { - return 1; - } - - return 0; -} - -# Try and be smart about what line the diff hunk starts on -sub start_line_calc { - my ($line_num,$diff_context) = @_; - my $ret; - - if ($line_num == 0 && $diff_context == 0) { - return 1; - } - - # Git defaults to three lines of context - my $default_context_lines = 3; - # Three lines on either side, and the line itself = 7 - my $expected_context = ($default_context_lines * 2 + 1); - - # The first three lines - if ($line_num == 1 && $diff_context < $expected_context) { - $ret = $diff_context - $default_context_lines; - } else { - $ret = $line_num + $default_context_lines; - } - - if ($ret < 1) { - $ret = 1; - } - - return $ret; -} - -# Remove + or - at the beginning of the lines -sub strip_leading_indicators { - my $line = shift(); # Array passed in by reference - my $columns_to_remove = shift(); # Don't remove any lines by default - - if ($columns_to_remove == 0) { - return $line; # Nothing to do - } - - $line =~ s/^(${ansi_color_regex})([ +-]){${columns_to_remove}}/$1/; - - if ($manually_color_lines) { - if (defined($5) && $5 eq "+") { - my $add_line_color = get_config_color("add_line"); - $line = $add_line_color . insert_reset_at_line_end($line); - } elsif (defined($5) && $5 eq "-") { - my $remove_line_color = get_config_color("remove_line"); - $line = $remove_line_color . insert_reset_at_line_end($line); - } - } - - return $line; -} - -# Insert the color reset code at end of line, but before any newlines -sub insert_reset_at_line_end { - my $line = shift(); - $line =~ s/^(.*)([\n\r]+)?$/${1}${reset_color}${2}/; - return $line; -} - -# Count the number of a given char in a string -# https://www.perturb.org/display/1010_Perl_Count_occurrences_of_substring.html -sub char_count { - my ($needle, $haystack) = @_; - - my $count = () = ($haystack =~ /$needle/g); - - return $count; -} - -# Remove all ANSI codes from a string -sub bleach_text { - my $str = shift(); - $str =~ s/\e\[\d*(;\d+)*m//mg; - - return $str; -} - -# Remove all trailing and leading spaces -sub trim { - my $s = shift(); - if (!$s) { return ""; } - - $s =~ s/^\s*//u; - $s =~ s/\s*$//u; - - return $s; -} - -# Print a line of em-dash or line-drawing chars the full width of the screen -sub horizontal_rule { - my $color = $_[0] || ""; - my $width = get_terminal_width(); - - # em-dash http://www.fileformat.info/info/unicode/char/2014/index.htm - #my $dash = "\x{2014}"; - # BOX DRAWINGS LIGHT HORIZONTAL http://www.fileformat.info/info/unicode/char/2500/index.htm - my $dash; - if ($use_unicode_dash_for_ruler && should_print_unicode()) { - #$dash = Encode::encode('UTF-8', "\x{2500}"); - $dash = "\xE2\x94\x80"; - } else { - $dash = "-"; - } - - # Draw the line - my $ret = $color . ($dash x $width) . "$reset_color\n"; - - return $ret; -} - -sub file_change_string { - my $file_1 = shift(); - my $file_2 = shift(); - - # If they're the same it's a modify - if ($file_1 eq $file_2) { - return "modified: $file_1"; - # If the first is /dev/null it's a new file - } elsif ($file_1 eq "/dev/null") { - my $add_color = $DiffHighlight::NEW_HIGHLIGHT[1]; - return "added: $add_color$file_2$reset_color"; - # If the second is /dev/null it's a deletion - } elsif ($file_2 eq "/dev/null") { - my $del_color = $DiffHighlight::OLD_HIGHLIGHT[1]; - return "deleted: $del_color$file_1$reset_color"; - # If the files aren't the same it's a rename - } elsif ($file_1 ne $file_2) { - my ($old, $new) = DiffHighlight::highlight_pair($file_1,$file_2,{only_diff => 1}); - # highlight_pair already includes reset_color, but adds newline characters that need to be trimmed off - $old = trim($old); - $new = trim($new); - return "renamed: $old$meta_color to $new" - # Something we haven't thought of yet - } else { - return "$file_1 -> $file_2"; - } -} - -# Check to see if STDIN is connected to an interactive terminal -sub has_stdin { - my $i = -t STDIN; - my $ret = int(!$i); - - return $ret; -} - -# We use this instead of Getopt::Long because it's faster and we're not parsing any -# crazy arguments -# Borrowed from: https://www.perturb.org/display/1153_Perl_Quick_extract_variables_from_ARGV.html -sub argv { - my $ret = {}; - - for (my $i = 0; $i < scalar(@ARGV); $i++) { - - # If the item starts with "-" it's a key - if ((my ($key) = $ARGV[$i] =~ /^--?([a-zA-Z_-]*\w)$/) && ($ARGV[$i] !~ /^-\w\w/)) { - # If the next item does not start with "--" it's the value for this item - if (defined($ARGV[$i + 1]) && ($ARGV[$i + 1] !~ /^--?\D/)) { - $ret->{$key} = $ARGV[$i + 1]; - # Bareword like --verbose with no options - } else { - $ret->{$key}++; - } - } - } - - # We're looking for a certain item - if ($_[0]) { return $ret->{$_[0]}; } - - return $ret; -} - -# Output the command line usage for d-s-f -sub usage { - my $out = color("white_bold") . version() . color("reset") . "\n"; - - $out .= "Usage: - -git diff --color | diff-so-fancy # Use d-s-f on one diff -cat diff.txt | diff-so-fancy # Use d-s-f on a diff/patch file -diff -u one.txt two.txt | diff-so-fancy # Use d-s-f on unified diff output - -diff-so-fancy --colors # View the commands to set the recommended colors -diff-so-fancy --set-defaults # Configure git-diff to use diff-so-fancy and suggested colors -diff-so-fancy --patch # Use diff-so-fancy in patch mode (interoperable with `git add --patch`) - -# Configure git to use d-s-f for *all* diff operations -git config --global core.pager \"diff-so-fancy | less --tabs=4 -RFX\" - -# Configure git to use d-s-f for `git add --patch` -git config --global interactive.diffFilter \"diff-so-fancy --patch\"\n"; - - return $out; -} - -sub get_default_colors { - my $out = "# Recommended default colors for diff-so-fancy\n"; - $out .= "# --------------------------------------------\n"; - $out .= '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 "yellow" -git config --global color.diff.frag "magenta 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" -'; - - return $out; -} - -# Output the current version string -sub version { - my $ret = "Diff-so-fancy: https://github.com/so-fancy/diff-so-fancy\n"; - $ret .= "Version : $VERSION\n"; - - return $ret; -} - -sub is_windows { - if ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2' or $^O eq 'cygwin' or $^O eq 'msys') { - return 1; - } else { - return 0; - } -} - -# Return value is whether this is the first time they've run d-s-f -sub check_first_run { - my $ret = 0; - - # If first-run is not set, or it's set to "true" - my $first_run = git_config_boolean('diff-so-fancy.first-run'); - # See if they're previously set SOME diff-highlight colors - my $has_dh_colors = git_config_boolean('color.diff-highlight.oldnormal') || git_config_boolean('color.diff-highlight.newnormal'); - - #$first_run = 1; $has_dh_colors = 0; - - if (!$first_run || $has_dh_colors) { - return 0; - } else { - print "This appears to be the first time you've run diff-so-fancy, please note\n"; - print "that the default git colors are not ideal. Diff-so-fancy recommends the\n"; - print "following colors.\n\n"; - - print get_default_colors(); - - # Set the first run flag to false - my $cmd = 'git config --global diff-so-fancy.first-run false'; - system($cmd); - - exit; - } - - return 1; -} - -sub set_defaults { - my $color_config = get_default_colors(); - my $git_config = 'git config --global core.pager "diff-so-fancy | less --tabs=4 -RFX"'; - my $first_cmd = 'git config --global diff-so-fancy.first-run false'; - - my @cmds = split(/\n/,$color_config); - push(@cmds,$git_config); - push(@cmds,$first_cmd); - - # Remove all comments from the commands - foreach my $x (@cmds) { - $x =~ s/#.*//g; - } - - # Remove any empty commands - @cmds = grep($_,@cmds); - - foreach my $cmd (@cmds) { - system($cmd); - my $exit = ($? >> 8); - - if ($exit != 0) { - die("Error running: '$cmd' (error #18941)\n"); - } - } - - return 1; -} - -# 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(); - - # 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); - $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; - - # Some predefined commands - my %cmd_map = qw(bold 1 italic 3 underline 4 blink 5 inverse 7); - my $cmd_num = $cmd_map{$cmd // 0}; - - my $ret = ''; - 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"; } - - return $ret; -} - -# Get colors used for various output sections (memoized) -{ - my $static_config; - - sub get_config_color { - my $str = shift(); - - 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"); - } - - # Cache (memoize) the entry for later - $static_config->{$str} = $ret; - - return $ret; - } -} - -# https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_colors_in_git -sub git_ansi_color { - my $str = shift(); - my @parts = split(' ', $str); - - if (!@parts) { - return ''; - } - my $colors = { - 'black' => 0, - 'red' => 1, - 'green' => 2, - 'yellow' => 3, - 'blue' => 4, - 'magenta' => 5, - 'cyan' => 6, - 'white' => 7, - }; - - my @ansi_part = (); - - if (grep { /bold/ } @parts) { - push(@ansi_part, "1"); - @parts = grep { !/bold/ } @parts; # Remove from array - } - - if (grep { /reverse/ } @parts) { - push(@ansi_part, "7"); - @parts = grep { !/reverse/ } @parts; # Remove from array - } - - my $fg = $parts[0] // ""; - my $bg = $parts[1] // ""; - - ############################################# - - # It's an numeric value, so it's an 8 bit color - if (is_numeric($fg)) { - if ($fg < 8) { - push(@ansi_part, $fg + 30); - } elsif ($fg < 16) { - push(@ansi_part, $fg + 82); - } else { - push(@ansi_part, "38;5;$fg"); - } - # It's a simple 16 color OG ansi - } elsif ($fg) { - my $bright = $fg =~ s/bright//; - my $color_num = $colors->{$fg} + 30; - - if ($bright) { $color_num += 60; } # Set bold - - push(@ansi_part, $color_num); - } - - ############################################# - - # It's an numeric value, so it's an 8 bit color - if (is_numeric($bg)) { - if ($bg < 8) { - push(@ansi_part, $bg + 40); - } elsif ($bg < 16) { - push(@ansi_part, $bg + 92); - } else { - push(@ansi_part, "48;5;$bg"); - } - # It's a simple 16 color OG ansi - } elsif ($bg) { - my $bright = $bg =~ s/bright//; - my $color_num = $colors->{$bg} + 40; - - if ($bright) { $color_num += 60; } # Set bold - - push(@ansi_part, $color_num); - } - - ############################################# - - my $ansi_str = join(";", @ansi_part); - my $ret = "\e[" . $ansi_str . "m"; - - return $ret; -} - -sub is_numeric { - my $s = shift(); - - if ($s =~ /^\d+$/) { - return 1; - } - - return 0; -} - -sub starts_with_ansi { - my $str = shift(); - - if ($str =~ /^$ansi_color_regex/) { - return 1; - } else { - return 0; - } -} - -sub get_terminal_width { - # Make width static so we only calculate it once - state $width; - - if ($width) { - return $width; - } - - # If there is a ruler width in the config we use that - if ($ruler_width) { - $width = $ruler_width; - # Otherwise we check the terminal width using tput - } else { - my $tput = `tput cols`; - - if ($tput) { - $width = int($tput); - - if (is_windows()) { - $width--; - } - } else { - print color('orange') . "Warning: `tput cols` did not return numeric input" . color('reset') . "\n"; - $width = 80; - } - } - - return $width; -} - -sub show_debug_info { - my @less = get_less_charset(); - my $git_ver = trim(`git --version`); - $git_ver =~ s/[^\d.]//g; - - print "Diff-so-fancy : v$VERSION\n"; - print "Git : v$git_ver\n"; - print "Perl : $^V\n"; - print "\n"; - - print "Terminal width : " . get_terminal_width() . "\n"; - print "Terminal \$LANG : " . ($ENV{LANG} || "") . "\n"; - print "\n"; - print "Supports Unicode: " . yes_no(should_print_unicode()) . "\n"; - print "Unicode Ruler : " . yes_no($use_unicode_dash_for_ruler) . "\n"; - print "\n"; - print "Less Charset Var: " . ($less[0] // "") . "\n"; - print "Less Charset : " . ($less[1] // "") . "\n"; - print "\n"; - print "Is Windows : " . yes_no(is_windows()) . "\n"; - print "Operating System: $^O\n"; -} - -sub yes_no { - my $val = shift(); - - if ($val) { - return "Yes"; - } else { - return "No"; - } -} - -# If there are colors set in the gitconfig use those, otherwise leave the defaults -sub init_diff_highlight_colors { - $DiffHighlight::NEW_HIGHLIGHT[0] = git_ansi_color(git_config('color.diff-highlight.newnormal')) || $DiffHighlight::NEW_HIGHLIGHT[0]; - $DiffHighlight::NEW_HIGHLIGHT[1] = git_ansi_color(git_config('color.diff-highlight.newhighlight')) || $DiffHighlight::NEW_HIGHLIGHT[1]; - - $DiffHighlight::OLD_HIGHLIGHT[0] = git_ansi_color(git_config('color.diff-highlight.oldnormal')) || $DiffHighlight::OLD_HIGHLIGHT[0]; - $DiffHighlight::OLD_HIGHLIGHT[1] = git_ansi_color(git_config('color.diff-highlight.oldhighlight')) || $DiffHighlight::OLD_HIGHLIGHT[1]; -} - -sub debug_log { - my $log_line = shift(); - my $file = "/tmp/diff-so-fancy.debug.log"; - - state $fh; - if (!$fh) { - printf("%sDebug log enabled:%s $file\n", color('orange'), color()); - open ($fh, ">", $file) or die("Cannot write to $file"); - } - - print $fh trim($log_line) . "\n"; - - return 1; -} - -# Enable k() and kd() if there is a DSF_DEBUG environment variable -BEGIN { - if ($ENV{"DSF_DEBUG"}) { - require Data::Dump::Color; - *k = sub { Data::Dump::Color::dd(@_) }; - *kd = sub { - k(@_); - - printf("Died at %2\$s line #%3\$s\n",caller()); - exit(15); - } - } else { - *k = sub {}; - *kd = sub {}; - } -} - -# vim: tabstop=4 shiftwidth=4 noexpandtab autoindent softtabstop=4 From c9df4a5a370eb0df63f77df19399718ec0024b94 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Fri, 9 Jun 2023 11:05:43 -0700 Subject: [PATCH 41/41] Code alignment for readability --- diff-so-fancy | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/diff-so-fancy b/diff-so-fancy index 34c9753..31d71e5 100755 --- a/diff-so-fancy +++ b/diff-so-fancy @@ -937,8 +937,8 @@ sub git_ansi_color { my $fg = $parts[0] // ""; my $bg = $parts[1] // ""; - set_ansi_color( $fg, 0, \@ansi_part, $colors ) if $fg; - set_ansi_color( $bg, 10, \@ansi_part, $colors ) if $bg; + set_ansi_color($fg, 0 , \@ansi_part, $colors) if $fg; + set_ansi_color($bg, 10, \@ansi_part, $colors) if $bg; ############################################# @@ -950,9 +950,10 @@ sub git_ansi_color { sub set_ansi_color { my ($color, $increment, $ansi_part, $colors) = @_; - my $base_code = 30 + $increment; + + my $base_code = 30 + $increment; my $base8_code = 38 + $increment; - my $ext_code = 82 + $increment; + my $ext_code = 82 + $increment; if (is_numeric($color)) { if ($color < 8) {