Upgrading to perl 5.26

This morning I decided to purge my 5.24 installation on my development PC and move to 5.26. Bad mistake. Many distributions still fail to build without PERL_USE_UNSAFE_INC=1, I might as well put the environment on my ~/.bashrc. These are the ones that hit me (after a few of these, I just built with PERL_USE_UNSAFE_INC=1): Compiler::Lexer (GOCCY), OrePAN (TOKUHIROM), Task::Weaken (ADAMK), Test::SubCalls (ADAMK), Test::Object (ADAMK), Term::Encoding (MIYAGAWA). Apparently, for many of these dists tickets/issues have been posted since 3 months ago but the authors/maintainers have simply not responded. Many authors have perhaps moved on to greener pastures, we need more adopters.

List of new CPAN distributions – May 2017

dist author version date abstract
AI-XGBoost PABLROD 0.001 2017-05-29T19:06:04 Perl wrapper for XGBoost library https://github.com/dmlc/xgboost
Acme-DotDotGone LNATION 0.01 2017-05-21T16:33:02 The great new Acme::DotDotGone!
Acme-Helloworld TOMCHA 0.01 2017-05-27T03:16:27 output 'Hello, world'
Acme-Study-perl NEILB 1.00 2017-05-11T13:35:15 turns baubles into trinkets
Acme-Testing-Permissions BOOK 0.001 2017-05-31T07:49:51 Test target for PAUSE permissions
Acme-Want5000trillion ANATOFUZ 0.01 2017-05-31T14:46:00 I want 5000trillion yen.
Alien-LibBigWig AYATES v0.3.3 2017-05-11T10:52:42 Installation of libBigWig for Perl
Alien-XPA DJERIUS 0.01 2017-05-12T21:14:48 Find or Build libxpa
AnyEvent-Net-MPD JJATRIA 0.001 2017-05-29T11:57:29 A non-blocking interface to MPD
App-Aliyun FAYLAND 0.01 2017-05-11T10:28:03 Aliyun Command Tools
App-CISetup DROLSKY 0.01 2017-05-26T16:48:34 Command line tools to generate and update Travis and AppVeyor configs for Perl libraries
App-DumpChromeHistory PERLANCAR 0.001 2017-05-30T10:33:44 Dump Chrome history
App-DumpOperaHistory PERLANCAR 0.001 2017-05-30T10:30:55 Dump Opera history
App-EvalServerAdvanced SIMCOP 0.001 2017-05-27T02:14:18 A more featured update to App::EvalServer
App-EvalServerAdvanced-Protocol SIMCOP 0.100 2017-05-26T21:14:11 Protocol abstraction for App::EvalServerAdvanced
App-EvalServerAdvanced-REPL SIMCOP 0.001 2017-05-26T23:02:41 Example client for App::EvalServerAdvanced
App-ExtractLinks RORYRJB 0.0.1 2017-05-29T14:01:58 extract href's in HTML docs to stdout
App-Git-Autofixup TORBIAK 0.001 2017-05-25T11:13:16 create fixup commits for topic branches
App-Repo ZDENEK 0.11 2017-05-09T16:40:56 create debian repository
App-TOMLUtils PERLANCAR 0.001 2017-05-09T12:49:14 TOML utilities
App-btcindo PERLANCAR 0.001 2017-05-31T12:39:16 CLI for bitcoin.co.id
App-dt PERLANCAR 0.001 2017-05-18T08:35:39 CLI data transformer
App-nodie ORKUN 1.00 2017-05-29T22:05:00 runs immortal processes
App-unicomb PERLANCAR 0.001 2017-05-04T09:28:52 Produce Unicode character with combining character
Beam-Service PREACTION 0.001 2017-05-05T05:01:51 Role for services to access Beam::Wire features
Bencher-Scenario-SortHashKeys PERLANCAR 0.001 2017-05-23T23:37:34 Benchmark Sort::HashKeys
Bencher-Scenario-TOMLParsingModules PERLANCAR 0.001 2017-05-09T12:49:25 Benchmark TOML parsing modules
Benchmark-Featureset-ParamCheck TOBYINK 0.001 2017-05-15T18:25:13 compare different parameter validation modules
Bio-DB-Big AYATES v1.0.0 2017-05-11T10:54:09 Perl interface to bigWigLib for accessing the kent big formats
BlankOnDev YUSRIDEB 0.1000 2017-05-31T00:53:26 BlankOnDev – Several Development tools for BlankOn GNU/Linux.
CPAN-Testers-Backend PREACTION 0.001 2017-05-13T10:10:11 Backend processes for CPAN Testers data and operations
CPAN-Uploader-Tiny SKAJI v0.0.1 2017-05-13T16:52:47
CPP-panda-lib SYBER v1.0.0 2017-05-11T12:59:24 Collection of useful functions and classes for C++.
Catalyst-Model-Data-MuForm JJNAPIORK 0.001 2017-05-26T00:32:10 Model adaptor for Data::MuForm
Catalyst-Plugin-BootstrapAlert CAGAO 0.20 2017-05-03T22:21:33 Replacement for Catalyst::Plugin::StatusMessage inline with Bootstrap alert names (success, info, warning, and danger).
CloudCron JLMARTIN 0.02 2017-05-18T14:50:56 A simple distributed cloud friendly cron for the masses
CloudCron-Worker JLMARTIN 0.02 2017-05-18T14:51:08 A worker process for CloudCron
CloudDeploy JLMARTIN 1.05 2017-05-18T09:34:52 A toolkit for building and managing AWS CloudFormation stacks
Data-Faker-Colour MGV 0.001 2017-05-31T15:09:54 Generate random colours
Date-Holidays-BY BESINT 0.2017.0 2017-05-30T09:39:01 Determine Belorussian official holidays and business days.
Devel-Jemallctl TVDW 0.01 2017-05-23T15:39:05 Insight into what Jemalloc is doing
Device-PaloAlto-Firewall PUGLET 0.01 2017-05-02T11:36:31 Interact with the Palo Alto firewall API
Dist-Zilla-Plugin-EnsureLatestPerl ETHER 0.001 2017-05-12T08:29:29 Ensure the author is releasing using the latest Perl
Dist-Zilla-Plugin-UseUnsafeInc ETHER 0.001 2017-05-13T12:11:54 Indicates the value of PERL_USE_UNSAFE_INC to use during installation
ElasticEmail ELASTICML 0.01 2017-05-17T11:35:18 The great new ElasticEmail!
File-PCAP MAMAWE v0.0.4 2017-05-04T08:53:16 a pure Perl library to read and write PCAP files
FileDirUtil MTW v0.01 2017-05-15T14:47:03 A Moose Role for basic File IO
Finance-BTCIndo PERLANCAR 0.001 2017-05-31T10:42:46 Trade with bitcoin.co.id (VIP) using Perl
GPSD-Parse STEVEB 0.01 2017-05-17T00:30:32 Parse, extract use the JSON output from GPS units
Geo-Coder-CA NHORNE 0.01 2017-05-09T21:44:45 Get data from http://geocoder.ca
Geo-Coder-XYZ NHORNE 0.01 2017-05-11T22:33:18 Provides a geocoding functionality using http:://geocoder.xyz
Geo-OSM-Imager FIREDRAKE 0.02 2017-05-04T10:56:01 simplifies plotting onto OpenStreetMap tiles
GitHub-Crud PRBRENAN 2017.512 2017-05-13T00:29:04 Create, Read, Update, Delete files on GitHub
GraphQL ETJ 0.01 2017-05-18T14:48:06 The great new GraphQL!
Hash-Normalize VPIT 0.01 2017-05-26T14:58:51 Automatically normalize Unicode hash keys.
IO-ReadPreProcess ADDW 0.8 2017-05-22T18:51:47 Macro processing built into IO::File replacement
Image-Sane RATCLIFFE 0.06 2017-05-11T19:54:47 Perl extension for the SANE (Scanner Access Now Easy) Project
Imgur-API MLHOLLEN v0.0.1 2017-05-14T03:20:06
JSON-Assert SGREEN 0.04 2017-05-26T03:12:20 Tests JPaths into an JSON Data structure for correct values/matches
LWP-CurlLog JACOBG 0.01 2017-05-29T22:14:05 Log LWP requests as curl commands
LWP-Throttle NHORNE 0.01 2017-05-26T16:43:03 Throttle requests to a site
LWP-UserAgent-Throttled NHORNE 0.02 2017-05-26T18:22:28 Throttle requests to a site
Lingua-IN-TGC RAJ 1.01 2017-05-17T13:52:05 Perl extension for tailored grapheme clusters for indian languages
Log-Any-Plugin-Format JJATRIA 0.01 2017-05-06T20:25:14 Add a formatting subroutine to your Log::Any adapter
Log-Any-Plugin-History JJATRIA 0.01 2017-05-06T20:23:41 Add a message history to a Log::Any adapter
MARC-File-XML GMCHARLT v1.0.5 2017-05-24T01:18:18 convert a MARC file to XML
MarpaX-ESLIF-ECMA404 JDDPAUSE 0.001 2017-05-13T07:20:52 JSON Data Interchange Format following ECMA-404 specification
Mojo-CallFire SADAMS 0.01 2017-05-21T02:03:10 A simple interface to the CallFire API
Mojo-CloudCheckr SADAMS 0.01 2017-05-19T04:55:03 A simple interface to the CloudCheckr API
Mojo-IOLoop-DNSNative COFFEE 0.001 2017-05-25T12:57:23 Async native DNS lookup
Mojolicious-Plugin-Mailgun MRAMBERG 0.01 2017-05-15T13:45:56 Easy Email sending with mailgun
MooX-Locale-Passthrough REHSACK 0.001 2017-05-31T14:46:12 provide API used in translator modules without translating
MooX-PDL2 DJERIUS 0.01 2017-05-31T03:19:49 A Moo based PDL 2.X object
MooseX-DataModel JLMARTIN 1.00 2017-05-09T15:31:03 Create object models from datastructures
NOLookup TROHAU 1.01 2017-05-03T13:40:32 a set of lookup modules for various Norwegian data services.
Net-Async-Github TEAM 0.001 2017-05-11T14:48:48 support for https://github.com's REST API with IO::Async
Net-Async-Graphite CHOHAG 0.0_1 2017-05-26T09:32:28 Request data from graphite
Net-Async-OAuth TEAM 0.001 2017-05-11T14:53:03 Basic OAuth support for async code
Net-Async-TravisCI TEAM 0.001 2017-05-11T15:38:57 API support for travis-ci.com and travis-ci.org
Net-Async-Trello TEAM 0.001 2017-05-11T12:49:54 Interaction with the trello.com API
Net-DNS-Extlang JRLEVINE 0.1 2017-05-14T03:16:00 DNS extension language
Net-Etcd HEXFUSION 0.008 2017-05-29T18:38:28 Provide access to the etcd v3 API.
Net-FTP-Path-Iter DJERIUS 0.02 2017-05-09T17:11:29 Iterative, recursive, FTP file finder
Net-FTP-Rule DJERIUS 0.01 2017-05-03T21:38:28 Iterative, recursive, FTP file finder
Net-Frame-Layer-MPLS VINSWORLD 1.00 2017-05-25T02:24:10 Multiprotocol Label Switching layer object
Net-Hacky-Detect-IP DAEMON 0.01 2017-05-07T10:29:44 Hackily try different methods of attaining local system IPs
Pcore-Ext ZDM v0.1.0 2017-05-01T20:03:51 ExtJS raw js generator
Perinci-Examples-ResMeta-Table PERLANCAR 0.001 2017-05-24T02:24:25 Demonstrate the various table and table.* result metadata property/attributes
Perl2Package MLHOLLEN v0.1.0 2017-05-15T01:27:28 Wrapper scripts to generate RPM/DEB packages
Plack-App-Catmandu-Bag NICS 0.01 2017-05-12T15:24:46 Plack application that wraps a REST API around a Catmandu::Bag
Plack-Middleware-Memento NICS 0.01 2017-05-19T10:14:41 Base role and interface for Plack::Middleware::Memento handlers
Plack-Middleware-Memento-Handler-Catmandu-Bag NICS 0.01 2017-05-19T11:36:09 Connect Plack::App::Catmandu::Bag to Plack::Middleware::Memento
Plack-Middleware-Signposting VPEIL 0.01 2017-05-29T18:44:22 A Signposting implementation from JSON content
RPi-Pin STEVEB 2.3601 2017-05-27T21:39:23 Access and manipulate Raspberry Pi GPIO pins
RT-Extension-RightsInspector BPS 0.02 2017-05-11T19:26:54 RT-Extension-RightsInspector Extension
Redis-ClusterRider IPH 0.01 2017-05-19T21:42:08 Daring Redis Cluster client
Ref-Util-XS XSAWYERX 0.114 2017-05-11T16:03:20 Utility functions for checking references
Reply-Plugin-Autocomplete-ExportedSymbols AKIYM 0.01 2017-05-28T11:13:08 Tab completion for exported symbol names
Resque-Plugin-Retry MERU 0.01 2017-05-08T09:43:15 Retry the fail job
Router-XS DFARRELL 0.01 2017-05-24T14:24:53 Fast URI path to value lookup
SNS-Notification JLMARTIN 0.02 2017-05-15T12:38:14 An object for representing SNS Notifications
SQS-Worker JLMARTIN 0.05 2017-05-15T14:43:59 A light framework for processing messages from SQS queues
Swagger-Schema JLMARTIN 1.00 2017-05-09T15:31:15 Object model for Swagger schema files
Sys-Linux-Namespace SIMCOP 0.001 2017-05-04T06:04:28 Sets up linux kernel namespaces
TOML-Examples PERLANCAR 0.001 2017-05-09T12:49:37 Example TOML configuration files
Test-HTTP-LocalServer CORION 0.57 2017-05-08T16:38:00 spawn a local HTTP server for testing
Test2-Plugin-IOSync EXODIST 0.000001 2017-05-02T03:10:14 Load IOEvents and IOMuxer so that they work together.
Text-ReadConditionally ADDW 0.72 2017-05-12T17:48:22 Macro processing built into IO::File replacement
Time-Moment-Epoch HEANEY 0.001 2017-05-20T13:47:59 Convert various epoch times to Time::Moment times.
URI-amqp JASEI 0.1.0 2017-05-23T08:04:18 AMQP (RabbitMQ) URI
VMOMI STUMPR 0.01 2017-05-02T23:21:41 VMware vSphere API Perl Bindings
VMware-vCloudDirector NIGELM 0.004 2017-05-04T14:26:03 Interface to VMWare vCloud Directory REST API
Verilog-VCD-Writer JVS 0.001 2017-05-23T22:35:53 VCD waveform File creation module.
WWW-Leech-Parser JAREDSPB 0.01 2017-05-07T10:46:35 HTML Page parser used by WWW::Leech::Walker
WWW-Leech-Walker JAREDSPB 0.01 2017-05-08T12:22:08 small web content grabbing framework
WWW-Mechanize-Plugin-Selector CORION 0.16 2017-05-12T13:04:28 CSS selector method for WWW::Mechanize
WebService-Naver-TTS AANOAA v0.0.1 2017-05-05T03:22:40 Perl interface to Naver TTS API
XS-Tutorial DFARRELL 0.01 2017-05-03T02:16:43 documentation with examples for learning Perl XS
Yandex-Dictionary BRNFLK 0.001 2017-05-15T14:53:55 a simple API for Yandex.Dictionary
Yandex-Translate BRNFLK 0.01 2017-05-02T17:05:45 Perl extension for using Yandex API
Zimbra-Expect OETIKER v0.1.0 2017-05-16T07:23:56 Execute multiple commands with a single instance of zmprov or zmmailbox and thus run magnitudes faster
chi-driver-elasticache-memcache ZEBARDY 0.01 2017-05-11T20:17:56 This is a CHI Driver for AWS's Elasticache memcache implementation
fastQ_brew HALLORAN 1.0.2 2017-05-09T20:18:31 Provides methods for fastQ file manipulation
fastQ_brew_ver HALLORAN 1.0.2 2017-05-12T17:36:44 Provides methods for fastQ file manipulation
geoip DANNYT 0 2017-05-11T14:44:44
graphcompare SCASTILLO v0.6.1 2017-05-25T12:49:23 A command-line tool to compare graph files in DOT or tabular format.
net-async-graphite CHOHAG 0.0 2017-05-25T19:26:47 Request data from graphite.

You can also browse new distributions on MetaCPAN. See also What’s new on CPAN – May 2017 (a curated list by David Farrell).

pericmd 048: Showing table data in browser as sortable/searchable HTML table

The latest release of Perinci::CmdLine (1.68) supports viewing program’s output in an external program. And also a new output format is introduced: html+datatables. This will show your program’s output in a browser and table data is shown as HTML table using jQuery and DataTables plugin to allow you to filter rows or sort columns. Here’s a video demonstration:

Your browser does not support the video tag, or WordPress filters the VIDEO element.

If the video doesn’t show, here’s the direct file link.

Call for collaboration: mini-article series on object systems and Dist::Zilla plugins

Aside from the mini-article series on option parsing modules that I have recently completed, there are two more series I currently have in mind: one on object systems (Moose, Mouse, Moo, Mo, Object::Tiny, Class::Accessor, and so on) and another on Dist::Zilla plugins. However, as I don't feel familiar with many of the modules or plugins, I think it would be nice if more people could write the articles.

The format of the series is 24-25 (mini-)articles, each comprised of minimum 250-300 words, 3-5 paragraphs. This is equivalent to the amount of text of a typical essay one is expected to write in a TOEFL test in 20-30 minutes time. So it should relatively easy to write even for non-native English speakers. I personally find that writing a blog post in 30-60 minutes time is ideal: it can be done in one sitting and does not take too much time to interrupt your daily work. It can even be done during a break. There is no maximum length limit.

Each article should discuss or review a single module. Ideally the author of the article is not the author or (co-)maintainer of the reviewed module. The article should first describe the module (its brief history, popularity, position in the CPAN river) then proceed to discussion on the user interface and design of the module and finally close with the author's overall view on the module (whether the module is well designed, whether the module is useful to her, whether the module is worth using compared to other modules).

If you are interested in collaborating, please contact me at perlancar gmail. I expect the series on object systems to be posted on Feb 1st, 2017 and the series on dzil plugins on Apr 1st.

x_* prereqs

Do you know that aside from the standard phases "develop", "configure", "build", "test", "runtime", and the standard relationship types "requires", "recommends", "suggests", you can also put arbitrary phase and relationship type in your Perl distribution's dependencies (prerequisites, a.k.a. prereqs) using x_ prefix?

The CPAN Meta Spec v2 (CPAN::Meta::Spec) already allows this, but until fairly recently when using Dist::Zilla you can't produce those custom phase/relationship into your distribution's META.json because CPAN::Meta::Prereqs drops all but the standard phases/relationships. But since version 2.150006, thanks to Karen Etheridge (ETHER) (commit link) they are no longer dropped.

What would one use those custom phase/relationship for? So far, Kent Fredric (KENTNL) is using x_examples custom phase to specify prerequisites for examples (which normally will not be installed by your typical CPAN client). Karen plans to "use some new prereq categories for travis to make use of when deciding what prereqs to install for different tasks."

I myself am using x_spec relationship (in the develop phase) to specify that a distribution follows some specification, for example all my distributions which contain some Rinci metadata is peppered with this. Another one is x_embed relationship. This is when I embed a module source code into another module using fatpacking technique using Module::FatPack, to reduce dependencies. The embedding distribution no longer needs to specify a runtime requires dependency for the embedded module, but I still would like to record the fact that the module is being embedded, so I can know when I want to update the embedded source sometime later.

The possibilities are endless.

A somewhat related issue, which is broader, more complex, and hasn't been solved, is specifying dependencies to things that are not Perl modules, e.g. an OS package, a certain program, a certain C library. (References: #79, #82).

Getopt modules: Epilogue

About this mini-article series. For each of the past 24 23 days, I have reviewed a module that parses command-line options (such module is usually under the Getopt::* namespace). First article is here.

This series was born out of my experimentations with option parsing and tab completion, and more broadly of my interest in doing CLI with Perl. Aside from writing this series, I've also released numerous modules related to option parsing, some of them are purely experimental in nature and some already used in production.

It has been interesting evaluating the various modules: the sometimes unconventional or seemingly odd approach that they take, or the specific features that they offer. Not all of them are worth using, but at least they provide perspectives and some lessons for us to learn.

Of course, not all modules got reviewed. There are simply far more than 24 modules (lcpan tells me that there are 180 packages in the Getopt:: namespace alone, with 94 distributions having the name Getopt-*). I tried to cover at least the must-know ones, core ones, and the popular ones. Other than that, frankly the selection is pretty much random. I picked what's interesting to me or what I can make some points about, whether they are negative or positive points.

I have skipped many modules that are just yet another Getopt::Long wrapper which adds per-option usage or some other features found in Getopt::Long::Descriptive (GLD). Not that they are worse than GLD, for some reason or another they just didn't get adopted widely or at all. A couple examples of these: Getopt::Helpful, Getopt::Fancy.

Modules which use Moose, except MooseX::Getopt, automatically get skipped by me because their applicability is severely limited by the high number of dependencies and high startup overhead (200-500ms or even more on slower computers). These include: Getopt::Flex, Getopt::Alt, Getopt::Chain.

Some others are simply too weird or high in "WTF number", but I won't name names here.

Except for App::Cmd and App::Spec, I haven't really touched CLI frameworks in general. There are no shortages of CLI frameworks on CPAN too, perhaps for another series?

I've avoided reviewing my own modules, which include Getopt::Long::Complete (Getopt::Long wrapper which adds tab completion), Getopt::Long::Subcommand (Getopt::Long wrapper, with support for subcommands), Getopt::Long::More (my most recent Getopt::Long wrapper which adds tab completion and other features), Getopt::Long::Less & Getopt::Long::EvenLess (two leaner versions of Getopt::Long for the specific goal of reducing startup overhead), Getopt::Panjang (a break from Getopt::Long interface compatibility to explore new possibilities), and a CLI framework Perinci::CmdLine (which currently uses Getopt::Long but plans to switch backend in the long run; I've written a whole series of tutorial posts for this module).

In general, I'd say that you should probably try to stick with Getopt::Long first. As far as option parsing is concerned, it's packed with features already, and it has the advantage of being a core module. But as soon as you want: automatic autohelp/automessage generation, subcommand, tab completion then you should begin looking elsewhere.

Unfortunately except for evaluating Perl ports of some option parsing libraries (like Smart::Options, Getopt::ArgParse, Getopt::Kingpin), I haven't got the chance to deeply look into how option parsing is done in other languages. Among the other languages is Perl's own sister Perl 6, which offers built-in command-line option parsing. This endeavor of researching option parsing in other languages could potentially offer more lessons and perspectives.

I hope this series is of use to some people. Merry christmas and happy holidays to everybody.

Getopt modules 23: Getopt::Complete

About this mini-article series. Each day for 24 days, I will be reviewing a module that parses command-line options (such module is usually under the Getopt::* namespace). First article is here.

Getopt::Complete (GC) is a module written by Scott Smith (SAKOHT) in 2009 and also co-maintained by Nathan Nutter (NNUTTER). Last release is in 2011. So far it registers one CPAN distribution depending on it, although it's written by Scott himself.

Shell tab completion is a topic which I have been interested in since around 2012. I've released numerous modules related to completion, including two option parsing modules Getopt::Long::Complete (GLC) and Getopt::Long::More (GLM) which sports completion as (one of) its selling point, so it's natural that I want to compare them to Getopt::Complete. Throughout the article I'll be repeatedly doing those comparisons, and I hope it's not becoming too annoying.


GC, like GLC and GLM, is a Getopt::Long (GL) wrapper that adds tab completion feature. To let the module detect tab completion mode and return completion answer as soon as possible, GC offers this interface:

use Getopt::Complete (
    'frog'        => ['ribbit','urp','ugh'],
    'fraggle'     => sub { return ['rock','roll'] },
    'quiet!'      => undef,
    'name'        => undef,
    'age=n'       => undef,
    'outfile=s@'  => 'files',
    'outdir'      => 'directories',
    'runthis'     => 'commands',
    'username'    => 'users',
    ''          => 'directories',

That is, it accepts the options specification as import arguments. This looks simple but presents its own inconveniences.

The second thing you'll notice that the options specification are different than GL. While GLC and GLM choose to use an interface that is backward-compatible with GL, GC focuses on tab completion. The values of the pairs in the options specification is not a variable reference/coderef as you would expect in GL, but solely completion specification: it's either undef (meaning the option does not require argument), a string (meaning a completion type/routine to use, e.g. files to complete from filenames, commands to complete from program names in PATH, and so on. The options values themselves are collected in %ARGS.

Thus, compared to GLC and GLM, specifying completion routines is simpler in GC (but I also wrote Shell::Completer to provide the same level of convenience with more flexibility).

Activating Completion

To activate completion in bash, you need to declare this shell function first:

function _getopt_complete () {

then for each CLI application you also need to do:

% complete -F _getopt_complete myapp

This is different than the way you activate completion for GLC- or GLM-based scripts:

% complete -C myapp myapp

External programs receive raw COMP_LINE and COMP_POINT environment variables from bash when doing tab completion, while shell functions are provided with the already-parsed command-line COMP_WORDS array variable and COMP_CWORD. GC wants to avoid parsing the command-line on its own, so the _getopt_complete function is used to give the Perl program parsed command-line arguments in @ARGV, and COMP_CWORD in another environment variable.

Using command-line that is already parsed by bash in COMP_WORDS has its pros as well as cons, due to the way that bash parses command-line for COMP_WORDS. So I cannot say which way is better, but what I can say is parsing COMP_LINE ourselves is more flexible.

Completion behavior and bugs

When you press tab after the command:

% myapp <tab>

GC offers only completion from the <> specification. In the above example, it only offers list of directories as answer. On the other hand, GLC and GLM also shows the list of available option names. With GC, to list the available options, you have to do:

% myapp -<tab>

I also cannot say that GLC's and GLM's way is better, but it certainly makes the CLI program more discoverable. By just pressing Tab, a user (especially a new user) can know more about what's possible.

GC has still a few problems. First of all, it cannot complete "–opt=" when COMP_WORDBREAKS contains "=". I have put workarounds for this issue in GLC and GLM. Second, it cannot handle filenames/directory names with spaces, or quotes, and probably other special characters too.

Third, GLC and GLM through Complete::Util offers some matching algorithms aside from simple prefix matching, for extra convenience. This is not offered by GC.