Is there an implementation of “getopt” for Delphi?

2020-02-23 08:34发布

问题:

It doesn't get much easier than using getopt() to parse command line parameters in C/C++.

Is there anything similar for Delphi? Or ideally, with the same syntax? I know Delphi supports FindCmdLineSwitch and ParamStr(), but those still require some additional parsing.

I want something that works like getopt() in C. Something that easily allows basic toggle switches, as well as capturing a value after a switch. See below for some example C code to see what I'm talking about:

void print_help()
{
        printf("usage:\n") ;
        printf("\t\t-i set input file\n") ;
        printf("\t\t-o set output file\n") ;
        printf("\t\t-c set config file\n") ;
        printf("\t\t-h print this help information\n") ;
        printf("\t\t-v print version\n") ;
}
 char* input_file = NULL ;
        char *query=NULL;
          char opt_char=0;
        while ((opt_char = getopt(argc, argv, "i:q:vh")) != -1)
        {
                switch(opt_char)
                {
                        case 'h':
                                print_help();
                                exit(-1);
                                break;
                        case 'v':
                                print_version() ;
                                exit(-1) ;
                                break ;
                        case 'i':
                                input_file= optarg ;
                                break ;
                        case 'q':
                                query= optarg ;
                                break ;
                        default:
                                print_help();
                                exit(-1);
                                break;
                }
        }

回答1:

There is an implementation TGetOpt, claiming to

implement a getopt variant for Delphi. It is nearly POSIX compatible, supporting long options, required, optional and no arguments

You can find it here.



回答2:

The getopts.pp file of the FPC RTL is self contained Delphi (Delphi2009 included) compatible unit that implements getopt :

Getopt implementation for Free Pascal, modeled after GNU getopt

The unit is available at the FPC SVN repository.



回答3:

See TCommandParser, described in this EDN article http://edn.embarcadero.com/print/40404 and available for download on CodeCentral http://cc.embarcadero.com/item/27574. TCommandParser should also be included in the Delphi demos now. I made the code freely available to Embarcadero before I left, so hopefully they'll include it in the framework or something like it at some point.



回答4:

Nothing built in - but you can make one pretty easily. This should be close to what you are used to

TsoCommandLineParser = class
private
  fArguments:TStringList;
public
  constructor Create();
  destructor Destroy(); override;

  function GetOpt(const pArgument:string; const pDefaultValue:string = ''):string;
end;


constructor TsoCommandLineParser.Create();
var
  i:Integer;
begin
  inherited Create();
  fArguments := TStringList.Create();
  for i := 1 to ParamCount() do
  begin
    fArguments.Add(ParamStr(i));
  end;
end;

destructor TsoCommandLineParser.Destroy();
begin
  fArguments.Free();
  inherited Destroy();
end;

function TsoCommandLineParser.GetOpt(const pArgument:string; const pDefaultValue:string = ''):string;
var
  i:Integer;
begin
  i := fArguments.IndexOfName(pArgument);
  if i > -1 then
  begin
    Result := fArguments.ValueFromIndex[i];
  end
  else
  begin
    Result := pDefaultValue;
  end;
end;


回答5:

What is wrong about FindCmdLineSwitch in the SysUtils unit?

if FindCmdLineSwitch('h',['-'],false) then
  Print_Help();
if FindCmdLineSwitch('v',['-'],false) then
  print_Version();

you will have to loop thru the params to get the values, but thats fairly simple to do:

if FindCmdLineSwitch('f',['-'],false) then
  for ix := 1 to paramcount do
    if (paramStr(ix) = '-f') and (ix < paramcount) then
      begin
        if fileExists( ParamStr(ix+1) ) then
          filename := ParamStr(ix+1);
        break;
      end


回答6:

There is also a new parser called delphi-argparse that is relevant to this question.



回答7:

Attribute-based parser for Delphi can be found here.



回答8:

There's the "Gastown Delphi Command Line Parser" which was recently open-sourced (e.g. on Torry's). I have never used it, so I can't comment on it.