Skip to content

Instantly share code, notes, and snippets.

@mlampret
Last active April 11, 2022 09:55
Show Gist options
  • Save mlampret/77065ba840cce2f3dab17dc9972e8dd2 to your computer and use it in GitHub Desktop.
Save mlampret/77065ba840cce2f3dab17dc9972e8dd2 to your computer and use it in GitHub Desktop.
Perl prompt for git directories
#!/usr/bin/env perl
# Copied and simplified from https://github.com/scottchiefbaker/perl-git-prompt/blob/master/git-prompt.pl
use strict;
use warnings;
use Cwd;
my $COLOR_PROMPT = color(7);
my $COLOR_DIRTY = color(1);
my $COLOR_CLEAN = color(2);
my $COLOR_DIR = color(4);
my $COLOR_RESET = color();
my $i = get_git_info();
my $pwd = getcwd;
if ($i && $i->{'branch'}) {
my $branch_color = $i->{'dirty'} ? $COLOR_DIRTY : $COLOR_CLEAN;
my $branch_name = $i->{'branch'};
my $root = `git rev-parse --show-toplevel`;
$root =~ s![^/]+\n$!!;
my $dir = $pwd;
$dir =~ s!^$root!!;
print ''
. $branch_color . $branch_name
. $COLOR_PROMPT . "@"
. $COLOR_DIR . $dir;
} else {
print $COLOR_DIR . $pwd;
}
print $COLOR_RESET . "\n\$ ";
sub color {
my $c = shift // '';
my $ret = "\e[0m";
$ret .= "\e[0m\e[38;5;${c}m" if $c;
return $ret;
}
sub get_git_info {
my $ret = {};
my $cmd = "2>/dev/null git status";
my $out = `$cmd`;
if ($out =~ /On branch (.+?)\n/) {
$ret->{'branch'} = $1;
} elsif ($out =~ /Not currently on any branch|HEAD detached (at|from)/) {
$ret->{'branch'} = "HEAD(detached)";
} else {
return 0;
}
if ($out =~ /Your branch is (ahead|behind).*'(.+?)' by (\d+) commit/) {
my $sigil = "?";
if ($1 eq 'ahead') {
$sigil = "+";
$ret->{'ahead'} = 1;
} elsif ($1 eq 'behind') {
$sigil = "-";
$ret->{'behind'} = 1;
}
my $str = "${sigil}$3";
$ret->{'position'} = $str;
}
if ($out =~ /^nothing to commit/m) {
$ret->{'clean'} = 1;
return $ret;
}
my $state;
foreach my $line (split(/\n/,$out)) {
if ($line =~ /Changes to be committed:/) {
$state = "staged";
} elsif ($line =~ /Changes not staged for commit:/) {
$state = "unstaged";
} elsif ($line =~ /Untracked files:/) {
$state = "untracked";
} elsif ($line =~ /Unmerged paths:/) {
$state = "unmerged";
} elsif ($line =~ /\t/) {
$ret->{$state}++;
$ret->{'dirty'}++;
}
}
return $ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment