go-ruby-getoptlong

Ruby's GetoptLong getopt-style option parser in pure Go โ€” MRI-identical messages, no cgo.

pure Go ยท zero cgo Ruby GetoptLong long ยท short ยท abbrev bundled / =joined args Permute ยท RequireOrder ยท ReturnInOrder -- terminator MRI-identical errors no global ARGV 100% coverage 6 arches
Documentation GitHub
Documentation (MkDocs Material + mike) License: BSD-3-Clause Go 1.26.4+ Coverage 100%

go-ruby-getoptlong is a pure-Go (no cgo) reimplementation of Ruby's GetoptLong โ€” the getopt-style command-line option parser bundled with MRI. It scans an argument list exactly as GetoptLong does: the same long / short / abbreviation matching, =-joined and separate arguments, bundled short flags, the -- terminator, the three ordering modes (Permute / RequireOrder / ReturnInOrder), and the full error taxonomy (InvalidOption / MissingArgument / NeedlessArgument / AmbiguousOption) with MRI-identical messages โ€” without any Ruby runtime. Unlike Ruby's global ARGV mutation, it operates on an explicit, Parser-owned slice and writes errors to a caller-supplied io.Writer, so it is reusable and free of global state. It is a standalone, reusable module โ€” the GetoptLong backend bound into go-embedded-ruby by rbgo, the same pattern as go-ruby-yaml โ€” differential-tested against MRI, 100% coverage, CI green across 6 arches and 3 OSes.

Long, short & abbreviated names ready

A long name may be given by any unique prefix; an ambiguous prefix raises AmbiguousOption. Options may carry any number of aliases and always report the canonical (first) name.

Argument forms ready

--name=value and --name value for long options; -nvalue, -n value, and bundled -abc for short options โ€” with MRI’s exact rules for NoArgument / RequiredArgument / OptionalArgument.

Ordering modes ready

Permute (default; options and operands mix), RequireOrder (options must precede operands), and ReturnInOrder (operands returned as ("", word)) โ€” plus the -- terminator.

Error taxonomy ready

InvalidOption, MissingArgument, NeedlessArgument, AmbiguousOption (all under Error) with the exact POSIX-format messages MRI produces, an optional $0-style program-name prefix, and a quiet mode.

No global state ready

Operates on a Parser-owned argv slice and a caller-supplied io.Writer instead of Ruby’s global ARGV / $0 / $stderr โ€” the host binds those to a Parser and reads leftover operands from Parser.Args.

Differential oracle & coverage ready

Every scenario โ€” all three orderings, name forms, argument forms, the terminator, each error class โ€” run through both this package and the system ruby and compared byte-for-byte (option stream, leftover argv, error class + message); 100% coverage, green across 6 arches and 3 OSes.

A faithful pure-Go port of Ruby's `GetoptLong`, cgo disabled, so it cross-compiles and embeds anywhere. Validated differentially against the system ruby binary, byte-for-byte. It is a standalone, reusable module extracted from rbgo's internals, and the backend bound by rbgo into the sibling org github.com/go-embedded-ruby.