%Copyright(C)2002,2003,2005DavidRoundy%%Thisprogramisfreesoftware;youcanredistributeitand/ormodify%itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby%theFreeSoftwareFoundation;eitherversion2,or(atyouroption)%anylaterversion.%%Thisprogramisdistributedinthehopethatitwillbeuseful,%butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof%MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe%GNUGeneralPublicLicenseformoredetails.%%YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense%alongwiththisprogram;seethefileCOPYING.Ifnot,writeto%theFreeSoftwareFoundation,Inc.,51FranklinStreet,FifthFloor,%Boston,MA02110-1301,USA.\begin{code}moduleDarcs.Commands(CommandControl(Command_data,Hidden_command,Group_name),DarcsCommand(DarcsCommand,command_name,command_help,command_description,command_basic_options,command_advanced_options,command_command,command_prereq,command_extra_arg_help,command_extra_args,command_argdefaults,command_get_arg_possibilities,SuperCommand,command_sub_commands),command_alias,command_stub,command_options,command_alloptions,disambiguate_commands,CommandArgs(..),get_command_help,get_command_mini_help,get_subcommands,usage,subusage,chomp_newline,extract_commands,super_name,nodefaults,loggers,)whereimportSystem.Console.GetOpt(OptDescr,usageInfo)importData.List(sort,isPrefixOf)importDarcs.Arguments(DarcsFlag,DarcsOption,disable,help,any_verbosity,posthook_cmd,posthook_prompt,prehook_cmd,prehook_prompt,option_from_darcsoption)importDarcs.RepoPath(AbsolutePath,rootDirectory)importDarcs.Utils(putStrLnError)importPrinter(Doc,putDocLn)\end{code}Thegeneralformatofadarcscommandis\begin{verbatim}%darcsCOMMANDOPTIONSARGUMENTS...\end{verbatim}Here\verb|COMMAND|isacommandsuchas\verb|add|or\verb|record|,whichofcoursemayhaveoneormorearguments.Optionshavetheform\verb!--option!or\verb!-o!,whileargumentsvaryfromcommandtocommand.Therearemanyoptionswhicharecommontoanumberofdifferentcommands,whichwillbesummarizedhere.Ifyouwish,youmayuseanyunambiguousbeginningofacommandnameasashortcut:for\verb!darcsrecord!,youcouldtype\verb!darcsrecor!or\verb!darcsrec!,butnot\verb!darcsre!sincethatcouldbeconfusedwith\verb!darcsreplace!,\verb!darcsrevert!and\verb!darcsremove!.Insomecases,\verb|COMMAND|actuallyconsistsoftwowords,asuper-commandandasubcommand.Forexample,the``displaythemanifest''commandhastheform\verb|darcsquerymanifest|.\paragraph{Commandoverview}Notallcommandsmodifythe``patches''ofyourrepository(thatis,thenamedpatcheswhichotheruserscanpull);somecommandsonlyaffectthecopyofthesourcetreeyou'reworkingon(your``workingdirectory''),andsomeaffectboth.Thistablesummarizeswhatyoushouldexpectfromeachoneandwillhopefullyserveasguidewhenyou'rehavingdoubtsaboutwhichcommandtouse.\begin{center}\footnotetext[1]{Butitaffectstherepositoryandworkingdirectorytargetedbythepush}\footnotetext[2]{Asfortheotherend,seeapply}\begin{tabular}{|c|c|c|}\hlineaffects&patches&workingdirectory\\\hlinerecord&yes&no\\\hlineunrecord&yes&no\\\hlinerollback&yes&yes\\\hlinerevert&no&yes\\\hlineunrevert&no&yes\\\hlinepull&yes&yes\\\hlineobliterate&yes&yes\\\hlineapply&yes&yes\\\hlinepush\footnote{Butitaffectstherepositoryandworkingdirectorytargetedbythepush}&no&no\\\hlinesend\footnote{Asfortheotherend,seeapply}&no&no\\\hlineput\footnote{Createsanewrepository}&no&no\\\hline\end{tabular}\end{center}\begin{code}extract_commands,extract_hidden_commands::[CommandControl]->[DarcsCommand]extract_commandscs=concatMap(\x->casexof{Command_datacmd_d->[cmd_d];_->[]})csextract_hidden_commandscs=concatMap(\x->casexof{Hidden_commandcmd_d->[cmd_d];_->[]})cs\end{code}\input{Darcs/Arguments.lhs}\begin{code}dataCommandControl=Command_dataDarcsCommand|Hidden_commandDarcsCommand|Group_nameStringdataDarcsCommand=DarcsCommand{command_name,command_help,command_description::String,command_extra_args::Int,command_extra_arg_help::[String],command_command::[DarcsFlag]->[String]->IO(),command_prereq::[DarcsFlag]->IO(EitherString()),command_get_arg_possibilities::IO[String],command_argdefaults::[DarcsFlag]->AbsolutePath->[String]->IO[String],command_basic_options::[DarcsOption],command_advanced_options::[DarcsOption]}|SuperCommand{command_name,command_help,command_description::String,command_prereq::[DarcsFlag]->IO(EitherString()),command_sub_commands::[CommandControl]}command_alloptions::DarcsCommand->([DarcsOption],[DarcsOption])command_alloptionsDarcsCommand{command_basic_options=opts1,command_advanced_options=opts2}=(opts1++[disable,help],any_verbosity++opts2++[posthook_cmd,posthook_prompt,prehook_cmd,prehook_prompt])-- Supercommands cannot be disabled.command_alloptionsSuperCommand{}=([help],[])-- Obtain options suitable as input to-- System.Console.Getopt, including the --disable option (which is-- not listed explicitly in the DarcsCommand definitions).command_options::AbsolutePath->DarcsCommand->([OptDescrDarcsFlag],[OptDescrDarcsFlag])command_optionscwdc=(convertbasic,convertadvanced)where(basic,advanced)=command_alloptionscconvert=concatMap(option_from_darcsoptioncwd)nodefaults::[DarcsFlag]->AbsolutePath->[String]->IO[String]nodefaults__xs=returnxsget_subcommands::DarcsCommand->[CommandControl]get_subcommandsc@(SuperCommand{})=command_sub_commandscget_subcommands_=[]command_alias::String->DarcsCommand->DarcsCommandcommand_aliasnc=c{command_name=n,command_help=desc++"\n"++command_helpc,command_description=desc}wheredesc="Alias for "++command_nameccommand_stub::String->String->String->DarcsCommand->DarcsCommandcommand_stubnhdc=c{command_name=n,command_help=h,command_description=d,command_command=\__->putStrh}usage::[CommandControl]->Stringusagecs="Usage: darcs COMMAND ...\n\nCommands:\n"++usage_helpercs++"\n"++"Use 'darcs COMMAND --help' for help on a single command.\n"++"Use 'darcs --version' to see the darcs version number.\n"++"Use 'darcs --exact-version' to get the exact version of this darcs instance.\n\n"++"Check bug reports at http://bugs.darcs.net/\n"subusage::DarcsCommand->Stringsubusagesuper=(usageInfo("Usage: darcs "++command_namesuper++" SUBCOMMAND ... "++"\n\n"++command_descriptionsuper++"\n\nSubcommands:\n"++usage_helper(get_subcommandssuper)++"\nOptions:")(option_from_darcsoptionrootDirectoryhelp))++"\n"++command_helpsuperusage_helper::[CommandControl]->Stringusage_helper[]=""usage_helper(Hidden_command_:cs)=usage_helpercsusage_helper((Command_datac):cs)=" "++pad_spaces(command_namec)15++chomp_newline(command_descriptionc)++"\n"++usage_helpercsusage_helper((Group_namen):cs)=n++"\n"++usage_helpercschomp_newline::String->Stringchomp_newline""=""chomp_newlines=iflasts=='\n'theninitselsespad_spaces::String->Int->Stringpad_spacessn=s++replicate(n-lengths)' 'super_name::MaybeDarcsCommand->Stringsuper_nameNothing=""super_name(Justx)=command_namex++" "get_command_mini_help::MaybeDarcsCommand->DarcsCommand->Stringget_command_mini_helpmsupercmd=get_command_help_coremsupercmd++"\n\nSee darcs help "++(maybe""(\c->command_namec++" ")msuper)++command_namecmd++" for details."get_command_help::MaybeDarcsCommand->DarcsCommand->Stringget_command_helpmsupercmd=unlines(reversebasicR)++(ifnulladvancedthen""else"\nAdvanced options:\n"++unlines(reverseadvancedR))++"\n"++command_helpcmdwhere-- we could just call usageInfo twice, but then the advanced-- options might not line up with the basic ones (no short flags)(advancedR,basicR)=splitAt(lengthadvanced)$reverse$linescombinedUsagecombinedUsage=usageInfo(get_command_help_coremsupercmd++subcommands++"\n\nOptions:")(basic++advanced)(basic,advanced)=command_optionsrootDirectorycmdsubcommands=casemsuperofNothing->caseget_subcommandscmdof[]->[]s->"\n\nSubcommands:\n"++(usage_helpers)-- we don't want to list subcommands if we're already specifying themJust_->""get_command_help_core::MaybeDarcsCommand->DarcsCommand->Stringget_command_help_coremsupercmd="Usage: darcs "++super_namemsuper++command_namecmd++" [OPTION]... "++unwordsargs_help++"\n"++command_descriptioncmdwhereargs_help=casecmdof(DarcsCommand___________)->command_extra_arg_helpcmd_->[]dataCommandArgs=CommandOnlyDarcsCommand|SuperCommandOnlyDarcsCommand|SuperCommandSubDarcsCommandDarcsCommand-- Parses a darcs command line with potentially abbreviated commandsdisambiguate_commands::[CommandControl]->String->[String]->EitherString(CommandArgs,[String])disambiguate_commandsallcscmdargs=doc<-extractcmdallcscase(get_subcommandsc,args)of([],_)->return(CommandOnlyc,args)(_,[])->return(SuperCommandOnlyc,args)(subcs,(a:as))->caseextractasubcsofLeft_->return(SuperCommandOnlyc,args)Rightsc->return(SuperCommandSubcsc,as)extract::String->[CommandControl]->EitherStringDarcsCommandextractcmdcs=case[c|c<-extract_commandscs,cmd`isPrefixOf`command_namec]++[h|h<-extract_hidden_commandscs,cmd==command_nameh]of[]->Left$"No such command '"++cmd++"'\n"[c]->Rightccs'->Left$"Ambiguous command...\n\n"++"The command '"++cmd++"' could mean one of:\n"++unwords(sort$mapcommand_namecs')-- | Output functions equivalent to (putStrLn, hPutStrLn stderr, putDocLn)loggers::[DarcsFlag]->(String->IO(),String->IO(),Doc->IO())loggers_=(putStrLn,putStrLnError,putDocLn)\end{code}