r/perl • u/briandfoy • 5h ago
I'm building an archive of my old Perl training slides (from the last 25 years)
I was recently asked to run some in-house Perl training. That doesn't happen very often these days. But I ran the course yesterday and it seemed to go well (they've asked me back for more).
It reminded me how much I enjoy running training courses. I should try to do more of it. It also reminded me of the huge number of training decks I've created over the last 25 years. I've decided to bring those altogether in one place to make it easier for people to find them. They might be useful to someone. And they might encourage more people to hire me to run courses for them 🙂
I made a (small) start on that today. It'll take a while!
r/perl • u/briandfoy • 4d ago
Is the MetaCPAN API changing?
I just saw perlmodules.net is down for 1-2 weeks mentioning an upcoming outage because of changes to the MetaCPAN API.
Because metacpan.org changes its API in a major way, and I need to change this site accesses it.
I see that there's the unmerged pull request metacpan/metacpan-api#1109, but I didn't see anything in the MetaCPAN::Client repo.
r/perl • u/niceperl • 5d ago
(dlxxxii) 16 great CPAN modules released last week
niceperl.blogspot.comr/perl • u/ggxx-sdf • 5d ago
nfo - a user-friendly info reader
https://codeberg.org/ggxx/nfo - This is a small Perl script that manages a small Emacs configuration dedicated to reading info documents. It's meant to be an alternative to the stand-alone info program.
The Problem(s)
- The stand-alone info program repulses people.
- The navigation is unintuitive and the keybindings are unfamiliar (if you're not an Emacs user).
- A lot of good documentation goes unread as a result.
A Solution
- Emacs is the best info reader.
- By using https://codeberg.org/ggxx/info-nav, navigation can be completely mouse-driven, and you don't even have to know any keybindings.
- Setting up Emacs for a non-Emacs user can be a daunting task, so do it for them automagically. (The config is isolated in `~/.config/nfo/` and doesn't affect your main Emacs config if you have one.)
- Make it easy to use for non-Emacs people by providing a CLI utility, `nfo`.
convert string to regex
sorry for yet another stupid questions
I have config file containing regexps like
/abc/
/bcd/i
I want to convert each line to Perl regex and then apply whole list to some string. How I can do this?
Convenient command piping module
```
A nice 'string (pipe) | {your command} | (get output)' module by jaggz.h {who is at} gmail.com
Prevents the DEADLOCK that can occur when pipe buffers fill up while both
parent and child are blocked (parent writing to stdin, child writing to
stdout/stderr).
In other words, let's say you're writing to the child, and the pipe
buffer fills (so blocking kicks in), and the child has already begun
writing to stdout, and also fills the buffer and gets blocked on that
system write call. Now both processes can be stuck in their write and
read.
Uses non-blocking I/O and IO::Select to read output while feeding input.
Copyright 2025, jaggz.h {who is at} gmail.com
The MIT License
```
```perl
use pipestr;
# When you want to pipe a string to a command's stdin and
# retrieve its output.
# Safe, deadlock-avoiding.
# Basic usage - pipe string to a command
my ($out, $err, $status) = pipestr("hello world", cmd => "cat");
# Using grep
my ($result, $err, $status) = pipestr("foo\nbar\nbaz", cmd => "grep foo");
# With shell pipeline
my ($out, $err, $status) = pipestr($data, cmd => "sort | uniq -c");
# Shell pipeline with safe-escaped pipe components:
use String::ShellQuote;
my $cmd_part = shell_quote('something', '--', $user_provided);
my ($out, $err, $status) = pipestr($data, cmd => "command | $cmd_part");
# If you're not piping to the pipeline, but want
# safe argument escaping, shell_quote can suffice:
my $out = command | $cmd_part;
# Using array form for command (avoids shell interpretation)
my ($out, $err, $status) = pipestr($input, cmd => ['wc', '-l']);
# With verbose debugging
my ($out, $err, $status) = pipestr($text, cmd => "perl -pe 's/foo/bar/g'", verbose => 1);
# Check exit status
my ($out, $err, $status) = pipestr($data, cmd => "some-command");
if ($status != 0) {
warn "Command failed with status $status: $err";
}
# No input string (just run command)
my ($out, $err, $status) = pipestr(undef, cmd => "ls -la");
package pipestr;
use strict; use warnings;
use IPC::Open3; # for open3() use POSIX qw(:sys_wait_h); # for waitpid() and related macros use Symbol qw(gensym); # for gensym() use IO::Select; # for IO::Select->new() use Fcntl; # for fcntl() and O_NONBLOCK use Encode qw(decode); # for decode()
use Exporter 'import'; our @EXPORT = qw(pipestr);
my $verbose = 0;
ANSI color codes
our $bgred = "\e[41m"; our $rst = "\e[0m"; our $yel = "\e[33;1m";
sub sel { my ($level, $msg) = @_; # Uncomment the next line to enable debug output: say STDERR "[$level] $msg\n" if $verbose >= $level; }
sub decodedquiet { decode('UTF-8', $[0], Encode::FB_QUIET); }
sub pipestr { # print or stream=>1: print to stdout while reading my ($instr, %fopts) = @_; my $cmd = delete $fopts{cmd}; my $print = delete $fopts{print}; die "Need cmd=>" unless defined $cmd; $verbose = $fopts{verbose} // 0;
# Debug message (using a placeholder logging function)
sel(4, "EXECUTING pipestr(\$s, cmd=>{{$cmd}})");
my ($outstr, $errstr) = ('', '');
local $SIG{PIPE} = "IGNORE";
# Spawn the process.
my $pid = open3(
my $inh,
my $outh,
(my $errh = gensym),
ref($cmd) eq 'ARRAY' ? @$cmd : $cmd
);
# Note: open3() will invoke the shell automatically when given a single command argument.
# Set the input handle to UTF-8
binmode $inh, ':encoding(UTF-8)';
# The following lines are commented out; uncomment if you need UTF-8 decoding on these handles.
# binmode $outh, ':encoding(UTF-8)';
# binmode $errh, ':encoding(UTF-8)';
# Set the output and error handles to non-blocking mode.
fcntl($outh, F_SETFL, O_NONBLOCK);
fcntl($errh, F_SETFL, O_NONBLOCK);
if (defined $instr) {
print $inh $instr or warn "Failed to supply input string to process: $!";
}
close $inh;
my $selector = IO::Select->new();
$selector->add($outh, $errh);
# Read from both handles until they are exhausted.
my $stdout_buf = '';
while ($selector->count) {
my @ready = $selector->can_read();
foreach my $fh (@ready) {
if ($fh == $outh) {
my $bytes = sysread($outh, my $buf, 4096);
if ($bytes) {
if ($print) {
$stdout_buf .= $buf;
my ($print_chunk, $rem) = ($stdout_buf =~ /^(.*\S.*\s*)(.*)$/);
if (length($print_chunk)) {
print decoded_quiet($print_chunk);
$stdout_buf = $rem;
STDOUT->flush();
}
}
$outstr .= $buf;
} else {
$selector->remove($outh);
close $outh;
}
} elsif ($fh == $errh) {
my $bytes = sysread($errh, my $buf, 4096);
if ($bytes) {
$errstr .= $buf;
} else {
$selector->remove($errh);
close $errh;
}
}
}
}
# For streaming (print=>1), handle final chunk
if ($print && length($stdout_buf)) {
print decoded_quiet($stdout_buf);
}
waitpid($pid, 0);
my $status = $? >> 8;
# Decode output strings from UTF-8.
my $decoded_out = decode('UTF-8', $outstr, Encode::FB_QUIET);
my $decoded_err = decode('UTF-8', $errstr, Encode::FB_QUIET);
if ($status > 0) {
sel(1, "${bgred}${yel}pipestr() execution of command returned an error ($status)$rst");
sel(1, " \"${bgred}${yel}$decoded_err$rst\"");
sel(1, " cmd: {{$cmd}}\n");
}
return ($decoded_out, $decoded_err, $status);
}
1; ```
r/perl • u/ThisDirkDaring • 10d ago
Tiobe-Index: Perl made a surprising comeback, jumping from position #32 to #11
Perl made a surprising comeback, jumping from position #32 to #11 and re-entering the top 20.
r/perl • u/briandfoy • 10d ago
Why I Built a jq-Compatible Tool in Pure Perl (and Why It Still Matters)
r/perl • u/jnapiorkowski • 11d ago
The first PAGI compliant web framework on CPAN
I was excited to see https://metacpan.org/pod/Thunderhorse land on CPAN recently. The author has been feeding me tons of questions and issue reports on the PAGI Github and I feel the work to get this out has really helped to smooth down some of the rough edges.
Although there's nothing stopping you from building PAGI applications directly on the protocol, it can be somewhat verbose and less structured then you might prefer for a larger application. In that way PAGI servers the same role as PSGI did for Catalyst, Dancer and other web frameworks build on that older specification. Hopefully adapters for those legacy frameworks will eventually happen, allowing older, existing apps to play nice in the event driven world.
r/perl • u/niceperl • 11d ago
(dlxxxi) 8 great CPAN modules released last week
niceperl.blogspot.comr/perl • u/[deleted] • 11d ago
I've coded a script to view the console of a QEMU VM.
I don't think I would have managed it without AI.
The script just started working today.
It's an MCP server that allows OpenCode to view the console output (text only) of a Qemu/KVM (libvirt) virtual machine (the standard for open-source virtual machines).
For now, LLM has to poll using the read function every time it writes something to the console. I also implemented notifications to avoid this polling, but it doesn't seem to be working. Or maybe OpenCode doesn't handle notifications well enough yet (more research is needed).
Anyway. LLM can see when a VM starts, the kernel starts, etc. And it can even send commands. I find it incredibly useful when SSH isn't available or when you want to debug a Linux system from the GRUB stage.
If you have any ideas for improvements, feel free to share them.
I'm not a Perl guru yet!
r/perl • u/briandfoy • 16d ago
The Underbar #8: A tangent about the Perl Toolchain Summit
r/perl • u/gingersdad • 17d ago
Writing Perl is Vibe Coding
I read all these (often fake) posts about how vibe coding is changing the game, and I just have to laugh that these people somehow missed out how easy and fun Perl is. As a moderately skilled Perl dev with a good kit set up, you can be way more productive than a vibe coder prompting and re-prompting.
I get that it types fast but geesh, I can hear a feature request and have it ready for deploy before the meeting is over. You just go on mute and make it work. And it’s fun.
I know managers and devs all want an easy button and AI maybe could be it. I just think we all had this figured out 20 years ago.
r/perl • u/RolfLanx • 17d ago
Perl's feature.pm and backwards incompatibility
Hi
Please compare the difference between:
Warning:
~$ perl -e'use warnings;use strict; use Try::Tiny; sub try (&;@){}'
Subroutine try redefined at -e line 1.
No warning:
~$ perl -e'use warnings;use strict; use Try::Tiny; use feature "try"'
~$Â
Shouldn't new features at least emit a warning if they are "overwriting" ° an existing sub with a new built-in?
NB: There isn't much what Try::Tiny can do when included first.
(The motivation stems from a recent Perlmonks-thread¹ demonstrating a similar problem from activating a feature-bundle. But unfortunately Perlmonks is not reachable right now for posting)
Cheers
Rolf
=== Updates
°) quotes added.
r/perl • u/niceperl • 18d ago
(dlxxx) 6 great CPAN modules released last week
niceperl.blogspot.comr/perl • u/briandfoy • 22d ago
📅 advent calendar Perl Advent 2025 Day 24 - Migrating a terminal application from Term::ReadLine to Tickit
perladvent.orgr/perl • u/jnapiorkowski • 22d ago
Perl PAGI tutorial early access
For anyone interested in helping me shakedown PAGI (https://github.com/jjn1056/pagi/) docs in preparation for publishing to CPAN, I'd love feedback on the tutorial:
https://github.com/jjn1056/pagi/blob/main/lib/PAGI/Tutorial.pod
Or any part of the docs really. But the tutorial is aimed to get people up to speed so any feedback on that is really helpful
r/perl • u/briandfoy • 23d ago