Help? Help.

The package optparse-applicative provides a Haskell library for parsing options at the command line.

A minimal example, providing only minimal help, is as follows:

On Windows 10, the ‘Usage:’ help text depends on how the executable is called and can include a filename extension. For example, at the Command Prompt, a test executable, opTest.exe, provides:

This behaviour differs from Windows 10’s native command line executables. For example:

I wanted to replicate the behaviour of the native executables in respect of the extension.

handleParseResult and getProgName

In package optparse-applicative-0.15.1.0, the origin of the executable name in the help text is progn <- getProgName in the implementation of the exported function Options.Applicative.Extra.handleParseResult. Function customExecParser relies on that function and execParser (used in the minimal example above) specialises customExecParser to defaultPrefs.

In package base-4.12.0.0, the Haddock documents for System.Environment.getProgName state:

Computation getProgName returns the name of the program as it was invoked.

However, this is hard-to-impossible to implement on some non-Unix OSes, so instead, for maximum portability, we just return the leafname of the program as invoked. Even then there are some differences between platforms: on Windows, for example, a program invoked as foo is probably really FOO.EXE, and that is what getProgName will return.

The explanation of what getProgName will return on Windows does not appear to be strictly accurate for Windows 10. A test with the following minimal example, compiled as gpnTest.exe, suggests that getProgName returns the name as it is invoked in Command Prompt. However, the filename (case aware) is returned in PowerShell or PowerShell Core or by double clicking on the file in Windows 10's File Explorer.

handleParseResult'

A more general handleParseResult' could take the program name as an argument, and similarly for execParser and customExecParser:

getProgName'

An action getProgName' could, on Windows, return the program name shorn of any extension, if the extension is the exeExtension. Package extra provides a convenient isWindows function.

However, System.FilePath.isExtensionOf is case-sensitive and the Windows file system is, by default, case-insensitive. Package case-insensitive provides a type which allows case-insensitive comparison of strings.

Then the revised minimal example would become: