Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changeset 2813

Show
Ignore:
Timestamp:
11/08/07 18:32:27 (1 year ago)
Author:
Jim Panic
Message:

closes #688

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tango/util/ArgParser.d

    r2809 r2813  
    3838*/ 
    3939alias void delegate () ArgParserSimpleCallback; 
     40 
     41 
     42/** 
     43    A struct that represents a "{Prefix}{Identifier}" string. 
     44*/ 
     45struct Argument { 
     46    char[] prefix; 
     47    char[] identifier; 
     48 
     49    /** 
     50        Creates a new Argument instance with given prefix and identifier. 
     51    */ 
     52    static Argument opCall ( char[] prefix, char[] identifier ) { 
     53        Argument result; 
     54 
     55        result.prefix = prefix; 
     56        result.identifier = identifier; 
     57 
     58        return result; 
     59    } 
     60} 
     61 
     62/** 
     63    Alias for for the lazy people. 
     64*/ 
     65alias Argument Arg; 
     66 
    4067 
    4168/** 
     
    154181 
    155182    /** 
    156         Parses the arguments provided by the parameter. The bound 
    157         callbacks are called as arguments are recognized. 
     183        Binds a delegate callback to an argument. 
     184 
     185        Params: 
     186            argument = argument to respond to 
     187            callback = the delegate that should be called when the argument is found 
     188    */ 
     189    public void bind (Argument argument, ArgParserCallback callback) { 
     190        bind(argument.prefix, argument.identifier, callback); 
     191    } 
     192 
     193    /** 
     194        Binds a delegate callback to any number of arguments. 
     195 
     196        Params: 
     197            arguments = an array of Argument struct instances 
     198            callback = the delegate that should be called when one of the arguments is found 
     199    */ 
     200    public void bind ( Argument[] arguments, void delegate(char[]) callback ) { 
     201        foreach (argument; arguments) { bind(argument, callback); } 
     202    } 
     203 
     204    /** 
     205        Binds a delegate callback to an identifier with Posix-like prefixes. This means, 
     206        it binds for both prefixes "-" and "--", as well as identifier with, and 
     207        without a delimiting "=" between identifier and value. 
     208 
     209        Params: 
     210            identifier = argument identifier 
     211            callback = the delegate that should be called when one of the arguments is found 
     212    */ 
     213    public void bindPosix ( char[] identifier, ArgParserCallback callback ) { 
     214        bind([ Argument("-", identifier ~ "="), Argument("-", identifier), 
     215               Argument("--", identifier ~ "="), Argument("--", identifier) ], callback); 
     216    } 
     217 
     218    /** 
     219        Binds a delegate callback to any number of identifiers with Posix-like prefixes. 
     220        See bindPosix(identifier, callback). 
     221 
     222        Params: 
     223            arguments = an array of argument identifiers 
     224            callback = the delegate that should be called when one of the arguments is found 
     225    */ 
     226    public void bindPosix ( char[][] identifiers, ArgParserCallback callback ) { 
     227        foreach (identifier; identifiers) { bindPosix(identifier, callback); } 
     228    } 
     229 
     230    /** 
     231        Parses the arguments provided by the parameter. The bound callbacks are called as 
     232        arguments are recognized. If two arguments have the same prefix, and start with  
     233        the same characters (e.g.: --open, --opened), the longest matching bound callback 
     234        is called. 
    158235 
    159236        Params: 
     
    163240    public void parse(char[][] arguments, bool resetOrdinals = false){ 
    164241        if (bindings.length == 0) return; 
     242 
    165243        if (resetOrdinals) { 
    166244            defaultOrdinal = 0; 
     
    172250        foreach (char[] arg; arguments) { 
    173251            char[] argData = arg; 
     252            char[] argOrig = argData; 
    174253            bool found = false; 
    175             char[] argOrig = argData; 
     254 
    176255            foreach (char[] prefix; prefixSearchOrder) { 
    177256                if(argData.length < prefix.length) continue;  
    178                 if(argData[0..prefix.length] != prefix) { 
    179                     continue; 
    180                 } 
    181                 else { 
    182                     argData = argData[prefix.length..$]; 
    183                 }  
     257 
     258                if(argData[0..prefix.length] != prefix) continue; 
     259                else argData = argData[prefix.length..$]; 
     260 
    184261                if (prefix in bindings) { 
     262                    PrefixCallback[] candidates; 
     263 
    185264                    foreach (PrefixCallback cb; bindings[prefix]) { 
    186265                        if (argData.length < cb.id.length) continue; 
     266                         
    187267                        uint cbil = cb.id.length; 
     268 
    188269                        if (cb.id == argData[0..cbil]) { 
    189270                            found = true; 
    190                             argData = argData[cbil..$]; 
    191                             cb.cb(argData); 
    192                             break; 
     271                            candidates ~= cb; 
    193272                        } 
     273                    } 
     274 
     275                    if (found) { 
     276                        // Find the longest matching callback identifier from the candidates. 
     277                        uint indexLongestMatch = 0; 
     278 
     279                        if (candidates.length > 1) { 
     280                            foreach (i, candidate; candidates) { 
     281                                if (candidate.id.length > candidates[indexLongestMatch].id.length) { 
     282                                    indexLongestMatch = i; 
     283                                } 
     284                            } 
     285                        } 
     286 
     287                        // Call the best matching callback. 
     288                        with(candidates[indexLongestMatch]) { cb(argData[id.length..$]); } 
    194289                    } 
    195290                }