From f564c7a4d60a4299a74d0cbb2efd8a56b1b490f5 Mon Sep 17 00:00:00 2001 From: wwwutz personal clanker Date: Thu, 22 Oct 2026 12:32:52 +0200 Subject: [PATCH 1/2] add CLAUDE.md Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..653296f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,34 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this is + +`chicken` is a chicken-ipsum text generator (a Perl port/extension of https://github.com/sebastiancarlos/chicken-ipsum). Plain Perl 5 with only core modules (`Getopt::Long`); no build system, no test suite, no dependencies to install. + +## Files + +- `chicken.pl` — the whole program. Installed as `/usr/bin/chicken`. +- `man_chicken.pl` — generator for the man page. Its `__DATA__` section is a roff template; every `$(args)` is replaced by the output of `./chicken.pl --seed args` (anything after the args, e.g. `| tr ...`, is passed through the shell as part of the `qx()` call). +- `chicken.1` — **generated** man page. Do not edit by hand; edit the template in `man_chicken.pl` and regenerate. +- `install.sh` — copies the script and man page into `${DESTDIR}/usr/bin` and `${DESTDIR}/usr/share/man/man1` (used for packaging with `bee`). + +## Commands + +```sh +./chicken.pl # one paragraph, 15-75 words +./chicken.pl -nw 10 --seed 42 # deterministic output +perl -c chicken.pl # syntax check +./man_chicken.pl > chicken.1 # regenerate the man page (must run from repo root; it calls ./chicken.pl) +man ./chicken.1 # view it +DESTDIR=/some/root ./install.sh # staged install +``` + +There are no tests. To verify a change, compare seeded output before/after (e.g. `./man_chicken.pl | diff - chicken.1`); the man page regeneration is fully deterministic and currently reproduces the committed `chicken.1` byte-for-byte. + +## Things that are easy to break + +- **Man page seeds derive from `$VERSION`.** `man_chicken.pl` starts at `seed = VERSION * 1000` and increments once per `$(...)` substitution, in template order. So bumping `$VERSION`, inserting/removing a `$(...)` in the template, or changing the order/number of `rand()` calls in `chicken.pl` changes the text of the whole (rest of the) man page. That's expected — just regenerate `chicken.1` and commit it together with the change. +- **When adding an option**, update three places: `GetOptions`/`USAGE` in `chicken.pl`, and the SYNOPSIS + Options sections of the template in `man_chicken.pl`; then regenerate `chicken.1`. +- `--maxlength` works by skipping words that don't fit. Skipped words must not affect capitalization, and the paragraph is closed off afterwards: the trailing space is removed and a `.` is added, with room for it held back during the loop. Keep the default (no `-ml`) path free of extra `rand()` calls so seeded output and the man page stay stable. +- `--namethischicken` builds its name pool from `@WORDS` (only words without a hyphen), so changing `@WORDS` changes the set of possible names. From a3020292ac13e44a9d01193ee130ee49be4e4278 Mon Sep 17 00:00:00 2001 From: wwwutz personal clanker Date: Thu, 22 Oct 2026 12:32:52 +0200 Subject: [PATCH 2/2] chicken: fix seeding, exit codes and --maxlength - seed: let perl seed itself unless --seed is given (time() repeated output within the same second); --seed 0 is now a real seed - exit 1 on bad --numberofwords format and on unknown options - --maxlength: skipped words no longer affect capitalization; drop the trailing space and terminate the sentence, reserving room for the '.' - namethischicken: use a named array instead of @_ - man_chicken.pl: use the argument passed to bokbokbok instead of $1 - fix typo "maximun" Seeded output without --maxlength and the generated man page are unchanged. Co-Authored-By: Claude Opus 5.5 --- chicken.pl | 32 +++++++++++++++++++++----------- man_chicken.pl | 5 +++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/chicken.pl b/chicken.pl index 5566f1c..33d9a81 100755 --- a/chicken.pl +++ b/chicken.pl @@ -10,14 +10,14 @@ sub USAGE { usage: $0 [options] --numberofwords -nw : number of words, ranged from n to m - --maxlength -ml : maximun length + --maxlength -ml : maximum length --enumerate -en : create a list of arguments --namethischicken : tell the chickens name --printchickenversion : print out "$VERSION" --seed : feed the random chicken eof - exit; + exit 1; } our %OPT; @@ -29,7 +29,7 @@ sub USAGE { my $opt_maxlength = 0; my $numberOfWords = 0; my $opt_namethischicken = 0; -my $opt_seed = 0; +my $opt_seed; my ( $f, $t ) = ( 0, 0 ); my $opt_enumerate = 0; @@ -48,7 +48,7 @@ sub USAGE { exit; } -srand( $opt_seed ? $opt_seed : time() ); +srand($opt_seed) if defined $opt_seed; my @WORDS = ( "puk", "pukaak", "cluck", "cluckity", "bwak", "waak", "bok", "bwok", "cluck-a-buh-gawk", "cock-a-doodle-doo", "bwwwaak", "gobble", "honk" ); @@ -57,6 +57,7 @@ sub USAGE { if ($opt_namethischicken) { my %ChickenPopulation; + my @MarriedChickens; my @ChickenNames = grep { !/-/ } @WORDS; for my $pn (@ChickenNames) { @@ -68,11 +69,11 @@ sub USAGE { # "Waak Bok" could also be married to "Cluck" which would end up in "Waak Bok-Cluck" for my $pn (@ChickenNames) { for ( keys %ChickenPopulation ) { - push @_, ucfirst($pn) . ' ' . $_ unless $ChickenPopulation{$_} == 1; + push @MarriedChickens, ucfirst($pn) . ' ' . $_ unless $ChickenPopulation{$_} == 1; } } - for (@_) { s/( \w+) /$1-/; $ChickenPopulation{$_} = 3 } + for (@MarriedChickens) { s/( \w+) /$1-/; $ChickenPopulation{$_} = 3 } my @CN = keys %ChickenPopulation; my $chickensname = $CN[ rand( scalar @CN ) ]; @@ -89,7 +90,7 @@ sub USAGE { else { print STDERR "wrong format for --numberofwords\n"; print STDERR "should be either 'n' or 'n-m'. ( '-nw 50' or '-nw 30-90''\n"; - exit; + exit 1; } my $enumerate = ($opt_enumerate) ? $opt_enumerate : 1; @@ -127,14 +128,17 @@ sub USAGE { # optionally capitalize the word # note: always capitalize if it's the first words, or if preceded by punctuation - my $shouldCapitalize = $i == 0 || $previousWordHadPunctuation || rand() > 0.7; + my $shouldCapitalize = $paragraph eq '' || $previousWordHadPunctuation || rand() > 0.7; $word = $shouldCapitalize ? uc( substr( $word, 0, 1 ) ) . substr( $word, 1 ) : $word; - # preserve info for next iteration - $previousWordHadPunctuation = $shouldAddPunctuation; + # keep room for a final '.' in case this ends up being the last word that fits + my $reserve = $shouldAddPunctuation ? 0 : 1; + + if ( $opt_maxlength == 0 or length($paragraph) + length($word) + $reserve <= $opt_maxlength ) { + # preserve info for next iteration + $previousWordHadPunctuation = $shouldAddPunctuation; - if ( $opt_maxlength == 0 or length($paragraph) + length($word) - 1 < $opt_maxlength ) { # add word to paragraph $paragraph = $paragraph . $word; @@ -143,6 +147,12 @@ sub USAGE { } } + # words may have been skipped by --maxlength: drop the trailing space and terminate the sentence + if ($opt_maxlength) { + $paragraph =~ s/ $//; + $paragraph .= '.' if $paragraph ne '' and $paragraph !~ /[.!?]$/; + } + if ($opt_enumerate) { printf "%d. ", $e + 1; } diff --git a/man_chicken.pl b/man_chicken.pl index c86a325..7bf1fcb 100755 --- a/man_chicken.pl +++ b/man_chicken.pl @@ -4,12 +4,13 @@ my $seed = $_ * 1000; sub bokbokbok { + my ($args) = @_; $seed++; - return qx(./chicken.pl --seed $seed $1); + return qx(./chicken.pl --seed $seed $args); }; while() { - s/\$\((.*?)\)/&bokbokbok($&)/eg; + s/\$\((.*?)\)/bokbokbok($1)/eg; print; }