The 6 basic shell colors are stored in an array. An arbitrary hash of the repo
name sets which color is used for the output.

Added CLI option -n, --nocolor.

Currently, "ver", "group" and "installed" are not bold. A single variable can
print them bold.

Now to_color() takes an array instead of a string. This removes the need for
another row of regex substitutions, while making the code shorter and faster.

Signed-off-by: Pierre Neidhardt <[email protected]>
---
 contrib/pacsearch.in | 113 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 62 insertions(+), 51 deletions(-)

diff --git a/contrib/pacsearch.in b/contrib/pacsearch.in
index 2418e19..d860471 100644
--- a/contrib/pacsearch.in
+++ b/contrib/pacsearch.in
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
-# pacsearch - Adds color and install information to a 'pacman -Ss' search
+# pacsearch - Perform a pacman search using both the local and the sync 
databases
 #
-# Copyright (C) 2008-2011 Dan McGee <[email protected]>
+# Copyright (C) 2008-2014 Dan McGee <[email protected]>
 #
 # Based off original shell script version:
 # Copyright (C) 2006-2007 Dan McGee <[email protected]>
@@ -19,9 +19,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-#TODO: colors flag on commandline
-#TODO: for now the whole line is bold and some parts have the same formatting 
(e.g. extra and version), maybe it would be better to use regular formatting
-
 use strict;
 use warnings;
 
@@ -31,13 +28,15 @@ my $myver = '@PACKAGE_VERSION@';
 sub usage {
        print "$myname (pacman) v$myver\n\n";
        print "Perform a pacman search using both the local and the sync 
databases.\n\n";
-       print "Usage: $myname <pattern>\n\n";
+       print "Usage: $myname [-n] <pattern>\n\n";
+       print "Options:\n";
+       print "  -n, --nocolor: turn off coloring\n\n";
        print "Example: $myname ^gnome\n";
 }
 
 sub version {
        printf "%s %s\n", $myname, $myver;
-       print "Copyright (C) 2008-2011 Dan McGee <dan\@archlinux.org>\n\n";
+       print "Copyright (C) 2008-2014 Dan McGee <dan\@archlinux.org>\n\n";
        print "Based off original shell script version:\n";
        print "Copyright (C) 2006-2007 Dan McGee <dan\@archlinux.org>\n";
 }
@@ -56,37 +55,47 @@ if ($ARGV[0] eq "--version" || $ARGV[0] eq "-V") {
 }
 
 # define formatting variables
-my $FMT_BLUE = "\e[1;94m";
-my $FMT_CYAN = "\e[1;96m";
-my $FMT_GREEN = "\e[1;92m";
-my $FMT_MAGENTA = "\e[1;95m";
-my $FMT_RED = "\e[1;91m";
-my $FMT_YELLOW = "\e[1;93m";
-my $FMT_BOLD = "\e[1m";
-my $FMT_RESET = "\e[0m";
+my $BLUE = "\e[94m";
+my $CYAN = "\e[96m";
+my $GREEN = "\e[92m";
+my $MAGENTA = "\e[95m";
+my $RED = "\e[91m";
+my $YELLOW = "\e[93m";
+my $BOLD = "\e[1m";
+my $REGULAR = "";
+my $RESET = "\e[0m";
+if ($ARGV[0] eq "--nocolor" || $ARGV[0] eq "-n") {
+       shift;
+       $BLUE = "";
+       $CYAN = "";
+       $GREEN = "";
+       $MAGENTA = "";
+       $RED = "";
+       $YELLOW = "";
+       $BOLD = "";
+       $REGULAR = "";
+       $RESET = "";
+}
+
+my @COLORS=($RED, $GREEN, $YELLOW, $BLUE, $MAGENTA, $CYAN);
+
+# We can choose if we output repo/pkgname bold or not. Same thing for 'ver 
group
+# installed'. Not sure if it's worth a CLI option.
+my $FMT_REPO = $BOLD;
+my $FMT_OTHER = $REGULAR;
 
 # Color a "repo/pkgname pkgver (goups) [installed]" line.
 # We try to stick to pacman colors.
 sub to_color {
-       my $line = shift;
-       # get the installed text colored first (between square brackets)
-       $line =~ s/(\[.*\]$)/$FMT_CYAN$1$FMT_RESET/;
-       # group (between parentheses)
-       $line =~ s/(\(.*\))/$FMT_BLUE$1$FMT_RESET/;
-       # version (second field)
-       $line =~ s/^([^ ]+) ([^ ]+) /$1 $FMT_GREEN$2$FMT_RESET /;
-       # name (word after slash)
-       $line =~ s/\/([\w-]*)/\/$FMT_BOLD$1$FMT_RESET/;
-       # repo (word before slash inclusive)
-       $line =~ s/(^core\/)/$FMT_BLUE$1$FMT_RESET/;
-       $line =~ s/(^extra\/)/$FMT_GREEN$1$FMT_RESET/;
-       $line =~ s/(^community\/)/$FMT_MAGENTA$1$FMT_RESET/;
-       $line =~ s/(^testing\/)/$FMT_CYAN$1$FMT_RESET/;
-       $line =~ s/(^community-testing\/)/$FMT_RED$1$FMT_RESET/;
-       $line =~ s/(^multilib\/)/$FMT_YELLOW$1$FMT_RESET/;
-       $line =~ s/(^local\/)/$FMT_CYAN$1$FMT_RESET/;
-       # any other unknown repository
-       $line =~ s/(^[\w-]*\/)/$FMT_YELLOW$1$FMT_RESET/;
+       my @v = @_;
+       # Each repo name is hashed to give a unique, persistant color index. The
+       # hash function (x*2+1) is completely arbitrary.
+       my $repohash = $v[0];
+       $repohash =~ s/(.)/ord($1)*2+1/ge;
+       my $repo_color=$COLORS[$repohash % 6];
+       my $line = "$RESET$FMT_REPO$repo_color$v[0]/$RESET$FMT_REPO$v[1]$RESET 
$GREEN$FMT_OTHER$v[2]$RESET";
+       $line .= " $BLUE$FMT_OTHER$v[3]$RESET" if $v[3] ne "";
+       $line .= " $CYAN$FMT_OTHER$v[4]$RESET" if $v[4] ne "";
        return $line;
 }
 
@@ -103,16 +112,17 @@ if ($#syncpkgs >= 0) {
 # counter var for packages, used here and in the query loop too
 my $cnt = 0;
 foreach $_ (@syncpkgs) {
-       # we grab 4 fields here: repo, name/ver, installed, and desc
-       my @pkgfields = /^(.*?)\/(.*?) ?(\[.*\])?\n(.*)$/s;
+       # we grab the following fields: repo, name, ver, group, installed, and 
desc
+       my @pkgfields = /^(.*?)\/(.*?) (.*?) ?(\(.*?\))? ?(\[.*\])?\n(.*)$/s;
        if(not @pkgfields) {
                # skip any non-matching line and just print it for the user
                print $_, "\n";
                next;
        }
-       # since installed is optional, we should fill it in if necessary
-       $pkgfields[2] = "" if not defined $pkgfields[2];
-       # add a fifth field that indicates original order
+       # since 'group' and 'installed' are optional, we should fill it in if 
necessary
+       $pkgfields[3] = "" if not defined $pkgfields[3];
+       $pkgfields[4] = "" if not defined $pkgfields[4];
+       # add a last field that indicates original order
        push (@pkgfields, $cnt++);
        # add each sync pkg by name/ver to a hash table for quick lookup
        $allpkgs{$pkgfields[1]} = [ @pkgfields ];
@@ -127,30 +137,31 @@ if ($#querypkgs >= 0) {
 }
 
 foreach $_ (@querypkgs) {
-       # we grab 4 fields here: repo, name/ver, installed, and desc
-       my @pkgfields = /^(.*?)\/(.*?) ?(\[.*\])?\n(.*)$/s;
+       # we grab the following fields: repo, name, ver, group, installed, and 
desc
+       my @pkgfields = /^(.*?)\/(.*?) (.*?) ?(\(.*?\))? ?(\[.*\])?\n(.*)$/s;
+       # my @pkgfields = /^(.*?)\/(.*?) ?(\[.*\])?\n(.*)$/s;
        # skip any non-matching line
        next if not defined $pkgfields[1];
-       # since installed is optional, we should fill it in if necessary
-       $pkgfields[2] = "" if not defined $pkgfields[2];
        # check if the package was listed in the sync out
        if (not exists $allpkgs{$pkgfields[1]}) {
-               $pkgfields[2] = "[installed]";
-               # add a fifth field that indicates original order (after sync)
+               # since 'group' is optional, we should fill it in if necessary
+               $pkgfields[3] = "" if not defined $pkgfields[3];
+               # TODO: localize the "installed" word
+               $pkgfields[4] = "[installed]";
+               # add a last field that indicates original order (after sync)
                push (@pkgfields, $cnt++);
                # add our local-only package to the hash
                $allpkgs{$pkgfields[1]} = [ @pkgfields ];
        }
 }
 
-# sort by original order (the fifth field) and print
-foreach $_ ( sort{ @{$allpkgs{$a}}[4] <=> @{$allpkgs{$b}}[4] } keys %allpkgs) {
+# sort by original order (the last field) and print
+foreach $_ ( sort{ @{$allpkgs{$a}}[6] <=> @{$allpkgs{$b}}[6] } keys %allpkgs) {
        my @v = @{$allpkgs{$_}};
-       my $line = "$v[0]/$v[1] $v[2]";
-       $line = to_color($line);
-       # print colorized "repo/pkgname pkgver" string with possible installed 
text
+       my $line = to_color(@v);
+       # print colorized "repo/pkgname pkgver ..." string with possible 
installed text
        print "$line\n";
-       print "$v[3]\n";
+       print "$v[5]\n";
 }
 
 #vim: set noet:
-- 
1.8.5.2

Reply via email to