From 9daedba7edc8753d21c69c59daecbfc2ae154aee Mon Sep 17 00:00:00 2001
From: bill-auger <mr.j.spam.me@gmail.com>
Date: Mon, 20 Mar 2023 12:01:53 -0400
Subject: [PATCH 1/5] implement animated cows

---
 cowsay | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 7 deletions(-)

diff --git a/cowsay b/cowsay
index 900ca46..dc49542 100755
--- a/cowsay
+++ b/cowsay
@@ -4,10 +4,12 @@
 ## Cowsay 3.03
 ##
 ## This file is part of cowsay.  (c) 1999-2000 Tony Monroe.
+## - animation feature: (c) 2023 bill-auger <bill-auger@programmer.net>
 ##
 
 use Text::Tabs qw(expand);
 use Text::Wrap qw(wrap fill $columns);
+use Time::HiRes qw ( usleep );
 use File::Basename;
 use Getopt::Std;
 use Cwd;
@@ -67,8 +69,29 @@ $Text::Wrap::columns = $opts{'W'};
 &construct_balloon;
 &construct_face;
 &get_cow;
-print @balloon_lines;
-print $the_cow;
+if (not @anim_files) {
+	&print_cow;
+}
+else {
+	my $anim_duration = 3000000;
+	my $n_anim_files = @anim_files;
+	my $sleep_ivl = $anim_duration / $n_anim_files;
+	my $clear_string = `clear`;
+
+	for my $full (@anim_files) {
+		do $full;
+		die "$progname: $@\n" if $@;
+
+		print $clear_string;
+		&print_cow;
+		usleep($sleep_ivl);
+	}
+}
+
+sub print_cow {
+	print @balloon_lines;
+	print $the_cow;
+}
 
 sub list_cowfiles {
     my $basedir;
@@ -77,10 +100,21 @@ sub list_cowfiles {
     for my $d (split(/$pathsep/, $cowpath)) {
 	print "Cow files in $d:\n";
 	opendir(COWDIR, $d) || die "$0: Cannot open $d\n";
-	for my $file (readdir COWDIR) {
-	    if ($file =~ s/\.cow$//) {
-		push(@dirfiles, $file);
-	    }
+	for my $file (grep !/^\.\.?$/, readdir COWDIR) {
+			# collect single cows
+			if ($file =~ s/\.cow$//) {
+				push(@dirfiles, $file);
+			}
+			# collect animated cows
+			elsif (-d "$d/$file") {
+				opendir(ACOWDIR, "$d/$file") || die "$0: Cannot open $d/$file\n";
+				for my $afile (readdir ACOWDIR) {
+					if ($afile =~ m/\.cow$/) {
+						push(@dirfiles, $file);
+						last;
+					}
+				}
+			}
 	}
 	closedir(COWDIR);
 	print wrap("", "", sort @dirfiles), "\n";
@@ -168,7 +202,19 @@ sub get_cow {
 	    } elsif (-f "$d/$f.cow") {
 		$full = "$d/$f.cow";
 		last;
-	    }
+		} elsif (-d "$d/$f") { # collect animated .cow files
+			opendir(ACOWDIR, "$d/$f") || die "$0: Cannot open $d/$f\n";
+			for my $file (sort (readdir ACOWDIR)) {
+				if ($file =~ m/\.cow$/) {
+					push(@anim_files, "$d/$f/$file");
+				}
+			}
+			if (@anim_files) {
+				return;
+			} else {
+				die "$progname: Could not find $f cowfiles!\n";
+			}
+		}
 	}
 	if ($full eq "") {
 	    die "$progname: Could not find $f cowfile!\n";
-- 
2.40.0

