unit CmdLineUtils; interface uses Windows, SysUtils, Contnrs, Utils; type TCmdOptions = class(TObject) private FIgnoreIDE: Boolean; FJclPath: string; FKeepFiles: Boolean; FIgnoreBCB: Boolean; FIgnoreDelphi: Boolean; FHelp: Boolean; FLang: string; FAutoUpdate: Boolean; FRegistryKeyDelphi: string; FRegistryKeyBCB: string; FRegistryKeyBDS: string; FItemList: TObjectList; procedure ShowHelp; protected procedure AddBool(const Name, Help: string; var Value: Boolean); procedure AddString(const Name, Help: string; var Value: string); procedure AddDir(const Name, Help: string; var Value: string); procedure AddSpace; procedure Init; virtual; public constructor Create; property IgnoreIDE: Boolean read FIgnoreIDE write FIgnoreIDE; property IgnoreBCB: Boolean read FIgnoreBCB write FIgnoreBCB; property IgnoreDelphi: Boolean read FIgnoreDelphi write FIgnoreDelphi; property JclPath: string read FJclPath write FJclPath; property KeepFiles: Boolean read FKeepFiles write FKeepFiles; property AutoUpdate: Boolean read FAutoUpdate write FAutoUpdate; property RegistryKeyDelphi: string read FRegistryKeyDelphi write FRegistryKeyDelphi; property RegistryKeyBCB: string read FRegistryKeyBCB write FRegistryKeyBCB; property RegistryKeyBDS: string read FRegistryKeyBDS write FRegistryKeyBDS; property Help: Boolean read FHelp; property Lang: string read FLang; end; var CmdOptions: TCmdOptions; implementation procedure TCmdOptions.Init; begin AddBool('--ignore-ide', 'Start installer even if Delphi/BCB is running.', FIgnoreIDE); AddBool('--ignore-bcb', 'Do not display and compile BCB versions.', FIgnoreBCB); AddBool('--ignore-delphi', 'Do not display and compile Delphi versions.', FIgnoreDelphi); AddSpace; AddDir('--jcl-path=', 'Set the JCL root directory to X.', FJclPath); AddBool('--keep-files', 'Do not call "clean".', FKeepFiles); AddBool('--autoupdate', 'Updates all IDEs where JVCL 3 is installed.', FAutoUpdate); AddSpace; AddString('-rDelphi=', 'Sets the Registry path for the Delphi IDEs.', FRegistryKeyDelphi); AddString('-rBCB=', 'Sets the Registry path for the BCB IDEs.', FRegistryKeyBCB); AddString('-rBDS=', 'Sets the Registry path for the BDS IDEs. (-rBDS=Win32Only)', FRegistryKeyBDS); AddString('--lang=', 'Sets the Installer''s language to X.', FLang); AddBool('--help', 'Show this screen.', FHelp); AddBool('/?', '', FHelp); AddBool('-h', '', FHelp); end; type TItem = class(TObject) private FName: string; FHelp: string; public constructor Create(const AName, AHelp: string); function IsItem(const ParStr: string): Boolean; virtual; property Name: string read FName; property Help: string read FHelp; end; TStringItem = class(TItem) private FValue: ^string; public constructor Create(const AName, AHelp: string; var Value: string); function IsItem(const ParStr: string): Boolean; override; end; TBoolItem = class(TItem) private FValue: ^Boolean; public constructor Create(const AName, AHelp: string; var Value: Boolean); function IsItem(const ParStr: string): Boolean; override; end; TDirItem = class(TStringItem) private function IsItem(const ParStr: string): Boolean; override; end; { TCmdOptions } procedure TCmdOptions.AddBool(const Name, Help: string; var Value: Boolean); begin FItemList.Add(TBoolItem.Create(Name, Help, Value)); end; procedure TCmdOptions.AddDir(const Name, Help: string; var Value: string); begin FItemList.Add(TDirItem.Create(Name, Help, Value)); end; procedure TCmdOptions.AddSpace; begin FItemList.Add(TItem.Create('', '')); end; procedure TCmdOptions.AddString(const Name, Help: string; var Value: string); begin FItemList.Add(TStringItem.Create(Name, Help, Value)); end; constructor TCmdOptions.Create; var i, Index: Integer; S: string; begin FItemList := TObjectList.Create; try Init; for i := 1 to ParamCount do begin S := ParamStr(I); for Index := 0 to FItemList.Count - 1 do begin if TItem(FItemList[Index]).IsItem(S) then Break; end; end; if Help then begin {$IFDEF MSWINDOWS} AllocConsole; {$ENDIF MSWINDOWS} ShowHelp; Halt(1); end; finally FItemList.Free; end; end; function PadString(const S: string; Count: Integer): string; var Len: Integer; begin Len := Length(S); if Len < Count then begin SetLength(Result, Count); Move(S[1], Result[1], Count); FillChar(Result[Len + 1], Count - Len, ' '); end else Result := S; end; procedure TCmdOptions.ShowHelp; var i: Integer; Item: TItem; S: string; begin WriteLn; for i := 0 to FItemList.Count - 1 do begin Item := TItem(FItemList[i]); if Item.Name = '' then WriteLn; if Item.Help <> '' then begin S := Item.Name; if Item is TStringItem then S := S + 'X'; WriteLn(PadString(S, 20), ' ', Item.Help); end; end; WriteLn; ReadLn; end; { TItem } constructor TItem.Create(const AName, AHelp: string); begin inherited Create; FName := AName; FHelp := AHelp; end; function TItem.IsItem(const ParStr: string): Boolean; begin Result := False; end; { TStringItem } constructor TStringItem.Create(const AName, AHelp: string; var Value: string); begin inherited Create(AName, AHelp); FValue := @Value; end; function TStringItem.IsItem(const ParStr: string): Boolean; begin Result := StartsWith(ParStr, Name, True); if Result then FValue^ := Copy(ParStr, Length(Name) + 1, MaxInt); end; { TBoolItem } constructor TBoolItem.Create(const AName, AHelp: string; var Value: Boolean); begin inherited Create(AName, AHelp); FValue := @Value; end; function TBoolItem.IsItem(const ParStr: string): Boolean; begin Result := CompareText(ParStr, Name) = 0; if Result then FValue^ := True else begin Result := CompareText(ParStr, Name + '-') = 0; if Result then FValue^ := False; end; end; { TDirItem } function TDirItem.IsItem(const ParStr: string): Boolean; var OldDir: string; begin OldDir := FValue^; Result := inherited IsItem(ParStr); if Result then if not DirectoryExists(FValue^) then FValue^ := OldDir; end; initialization CmdOptions := TCmdOptions.Create; finalization CmdOptions.Free; end.