I'm writing a program that has both a command-line interface and an interactive mode. In CLI mode it executes one command, prints results and exits. In interactive mode it repeatedly reads commands using GNU readline, executes them and prints results (in spirit of a REPL).
The syntax for commands and their parameters is almost the same regardless of whether they come from command-line or frmo stdin. I would like to maximize code-reuse by using a single framework for parsing both command-line and interactive mode inputs.
My proposed syntax is (square brackets denote optional parts, braces repetition) as follows:
From shell:
program-name {[GLOBAL OPTION] ...} <command> [{<command arg>|<GLOBAL OPTION>|<LOCAL OPTION> ...}]In interactive mode:
<command> [{<command arg>|<GLOBAL OPTION>|<LOCAL OPTION> ...}]
Local options are only valid for one particular command (different commands may assign a different meaning to one option).
My problem is that there are some differences between the CL and interactive interfaces: Some global options are only valid from command line (like --help, --version or --config-file). There is obviously also the 'quit'-command which is very important in interactive mode, but using it from CL makes no sense.
To solve this I've searched web and hackage for command-line parsing libraries. The most interesting ones I've found are cmdlib and optparse-applicative. However, I'm quite new to Haskell and even though I can create a working program by copying and modifying example code from library docs, I haven't quite understood the mechanics of these libraries and therefore have not been able to solve my problem.
I have these questions in mind:
How to make a base parser for commands and options that are common to CL and REPL interfaces and then be able to extend the base parser with new commands and options?
How to prevent these libraries from exiting my program upon incorrect input or when '--help' is used?
I plan to add complete i18n support to my program. Therefore I would like to prevent my chosen library from printing any messages, because all messages need to be translated. How to achieve this?
So I wish you could give me some hints on where to go from here. Does cmdlib or optparse-applicative (or some other library) support what I'm looking for? Or should I revert to a hand-crafted parser?
GetOptsdoesn't crash, it returns error message, as I'd assume any good library should do. It also doesn't do any printing, because printing has nothing to do with command line parsing.