# Note on Cliparser
# Table of Contents
- [Note on Cliparser](#note-on-cliparser)
- [Table of Contents](#table-of-contents)
  - [cliparser setup and use](#cliparser-setup-and-use)
  - [design comments](#design-comments)
  - [common options](#common-options)
  - [How to implement in source code](#how-to-implement-in-source-code)
    - [setup the parser data structure](#setup-the-parser-data-structure)
    - [define the context](#define-the-context)
    - [define the options](#define-the-options)
    - [Notes:](#notes)
      - [bool option.  true if supplied](#bool-option--true-if-supplied)
      - [integer that is optional](#integer-that-is-optional)
      - [integer that is required](#integer-that-is-required)
      - [double that is optional](#double-that-is-optional)
      - [double that is required](#double-that-is-required)
      - [String option that is optional and only one instance can be provided](#string-option-that-is-optional-and-only-one-instance-can-be-provided)
      - [String option that is required and only one instance can be provided](#string-option-that-is-required-and-only-one-instance-can-be-provided)
      - [String option that is optional and can have up to 250 instances provided](#string-option-that-is-optional-and-can-have-up-to-250-instances-provided)
      - [String option that is required/at least one instance and can have up to 250 instances](#string-option-that-is-requiredat-least-one-instance-and-can-have-up-to-250-instances)
      - [unsigned integer optional](#unsigned-integer-optional)
      - [unsigned integer required](#unsigned-integer-required)
    - [show the menu](#show-the-menu)
    - [clean up](#clean-up)
    - [retrieving options](#retrieving-options)
The old style with mixed custom commandline parsing of user parameters or options was messy and confusing.  You can find all kinds in the Proxmark3 client.
Samples
```
data xxxx h
script run x.lua -h
hf 14a raw -h
hf 14b raw -ss
lf search 1
lf config h H
```
even the external tools which we collected into this repo,  under folder */tools/* folder uses their own argument parsing.
In order to counter this and unify it,  there was discussion over at the official repository a few years ago [link to issue](https://github.com/Proxmark/proxmark3/issues/467) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
```
[usb] pm3 --> emv
[usb] pm3 --> hf fido
```
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there.
Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client.
After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way.
The aftermath was a design and layout specified which lead to a simpler implementation of the cliparser in the client source code while still unifying all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.

Furthermore @mrwalker offered to take notes and thus this document was created.
This is the _new_ and _preferred_ way to implement _helptext_ and _cli parsing_ for Proxmark3 client commands and it's external tools.
## cliparser setup and use
^[Top](#top)
The parser will format and color and layout as needed.
It will also add the `-h --help` option automatic.
## design comments
^[Top](#top)
* where possible all options should be lowercase.
* extended options preceded with -- should be short
* options provided directly (without an option identifier) should be avoided.
* -vv for extra verbose should be avoided; use of debug level is preferred.
* with --options the equal is not needed (will work with and without) so don't use '='
  e.g. cmd --cn 12345
## common options
^[Top](#top)
    -h --help       : help
    --cn            : card number
    --fn            : facility number
    --q5            : target is LF T5555/Q5 card
    --em            : target is LF EM4305/4469 card
    --raw           : raw data
    -d --data       : hex data supplied
    -f --file       : filename supplied
    -k --key        : key supplied
    -n --keyno      : key number to use
    -p --pwd        : password supplied
    -v --verbose    : flag when output should provide more information, not considered debug.
    -1 --buffer     : use the sample buffer
## How to implement in source code
^[Top](#top)
### setup the parser data structure
^[Top](#top)
Header file to include
    #include "cliparser.h"
In the command function, setup the context
    CLIParserContext *ctx;
### define the context
^[Top](#top)
`CLIParserInit (\, \, \);`
use -> to separate example and example comment and \\n to separate examples.
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
    CLIParserInit(&ctx, "lf indala clone",
                  "clone INDALA UID to T55x7 or Q5/T5555 tag",
                  "lf indala clone --heden 888\n"
                  "lf indala clone --fc 123 --cn 1337\n"
                  "lf indala clone -r a0000000a0002021\n"
                  "lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
### define the options
^[Top](#top)
    void *argtable[] = {
        arg_param_begin,
        arg_lit0("l", "long", "optional - long UID 224 bits"),
        arg_int0("c", "heden", "", "Cardnumber for Heden 2L format"),
        arg_str0("r", "raw", "", "raw bytes"),
        arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
        arg_int0(NULL, "fc", "", "Facility Code (26 bit format)"),
        arg_int0(NULL, "cn", "", "Cardnumber (26 bit format)"),
        arg_param_end
    };
_All options has a parameter index,  since `-h --help` is added automatic, it will be assigned index 0.
Hence all options you add will start at index 1 and upwards. It added in the define "arg_param_begin_
### Notes:
^[Top](#top)
#### bool option.  true if supplied
`bool : arg_lit0 ("", "", <"description">)`
#### integer that is optional
`optional integer : arg_int0 ("", "", "", <"description">)`
#### integer that is required
`required integer : arg_int1 ("", "", "", <"description">)`
#### double that is optional
`optional double : arg_dbl0 ("", "", "", <"description">)`
#### double that is required
`required double : arg_dbl1 ("", "", "", <"description">)`
#### String option that is optional and only one instance can be provided
`optional string : arg_str0 ("", "", "", <"description">)`
#### String option that is required and only one instance can be provided
`required string : arg_str1 ("", "", "", <"description">)`
#### String option that is optional and can have up to 250 instances provided
`optional string : arg_strx0 ("", "", "", <"description">)`
#### String option that is required/at least one instance and can have up to 250 instances
`required string : arg_strx1 ("", "", "", <"description">)`
Unsigned values, like  u32 and u64 can be accomplished with
#### unsigned integer optional
`optional unsigned : arg_u64_0 ("", "", "", <"description">)`
#### unsigned integer required
`required unsigned : arg_u64_1 ("", "", "", <"description">)`
**if an option does not have a short or long option, use NULL in its place**
### show the menu
^[Top](#top)
`CLIExecWithReturn(\, \, \, \);`
    CLIExecWithReturn(ctx, Cmd, argtable, false);
### clean up
^[Top](#top)
Once you have extracted the options, cleanup the context.
    CLIParserFree(ctx);
### retrieving options
^[Top](#top)
The parser will format and color and layout as needed.
It will also add the `-h --help` option automatic.
**bool option**
arg_get_lit(\, \);
    is_long_uid = arg_get_lit(ctx, 1);
**int option**
arg_get_int_def(\, \, \);
    cardnumber = arg_get_int_def(ctx, 2, -1);
**uint32**
arg_get_u32_def(\, \, \);
    cardnumber = arg_get_u32_def(ctx, 2, 0);
**uint64**
arg_get_u64_def(\, \, \);
    cardnumber = arg_get_u64_def(ctx, 2, 0);
**hex option with return**
CLIGetHexWithReturn(\, \, \, \);
    ?? as an array of uint_8 ??
    If failed to retrieve hexbuff, it will exit fct
    uint8_t aid[2] = {0};
    int aidlen;
    CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
**hex option**
    uint8_t key[24] = {0};
    int keylen = 0;
    int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen);
    quick test : seems res_keylen == 0 when ok so not key len ???
**string option return**
CLIGetStrWithReturn(\,\, \, \);
    If failed to retrieve string, it will exit fct
    uint8_t buffer[100] = {0};
    int slen = sizeof(buffer) - 1; // <- slen MUST be the maximum number of characters that you want returned. e.g. Buffer Size - 1 if you need it to be null-terminated!
    CLIGetStrWithReturn(ctx, 1, buffer, &slen);
**string option**     
Getting a char array 
    int slen = 0;
    char format[16] = {0};
    int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &slen);
    quick test : seem res == 0, then ok.  compare res == slen to see how many chars