Changeset 78

Show
Ignore:
Timestamp:
01/12/07 19:11:37 (2 years ago)
Author:
KirkMcDonald
Message:

Bug fixes, proper Unicode support.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • misc/optparse.d

    r77 r78  
    3030import std.conv : toInt, ConvError; 
    3131import std.path : getName, getBaseName; 
     32import std.utf : toUTF8, toUTF32; 
    3233 
    3334/* 
     
    6768    if (s.length < start.length) return false; 
    6869    return s[0 .. start.length] == start; 
     70} 
     71bool endswith(char[] s, char[] end) { 
     72    if (s.length < end.length) return false; 
     73    return s[$ - end.length .. $] == end; 
    6974} 
    7075 
     
    293298    } 
    294299    // Returns true if the passed option string matches this option. 
    295     bool matches(char[] arg) { 
     300    bool matches(char[] _arg) { 
     301        dchar[] arg = toUTF32(_arg); 
    296302        if ( 
    297303            arg.length < 2 || 
     
    303309        if (arg.length == 2) { 
    304310            foreach (opt; shortopts) { 
    305                 if (arg == opt) { 
     311                if (_arg == opt) { 
    306312                    return true; 
    307313                } 
     
    309315        } else { 
    310316            foreach (opt; longopts) { 
    311                 if (arg == opt) { 
     317                if (_arg == opt) { 
    312318                    return true; 
    313319                } 
     
    385391        char[] result; 
    386392        version(Windows) { 
     393            // (Unicode note: ".exe" only contains 4 code units, so this slice 
     394            // should Just Work.) (Although it remains to be seen how robust 
     395            // this code actually is.) 
    387396            assert(path[$-4 .. $] == ".exe"); 
    388397            result = path[0 .. $-4]; 
     
    415424        */ 
    416425        char[] opt, newopt, arg; 
     426        dchar[] opt32; 
    417427        int idx; 
    418428        Option match; 
     
    422432            // -- ends the option list, the remainder is dumped into args 
    423433            if (opt == "--") { 
    424                 if (this.leftover_cb is null) { 
    425                     foreach(arg; args[i+1 .. $]) { 
    426                         this.leftover_cb(arg); 
     434                if (this.leftover_cb !is null) { 
     435                    foreach(a; args[i+1 .. $]) { 
     436                        this.leftover_cb(a); 
    427437                    } 
    428438                } else { 
     
    435445                    newopt = opt[0 .. idx]; 
    436446                    // Stitch out the old arg, stitch in the newopt, arg pair. 
     447                    // (Unicode note: idx+1 works, since we know '=' is a 
     448                    // single code unit.) 
    437449                    args = args[0 .. i] ~ [newopt, opt[idx+1 .. $]] ~ args[i+1 .. $]; 
    438450                } else { 
     
    453465            } else if (opt.startswith("-")) { 
    454466                if (opt.length >= 2) { 
    455                     foreach (j, c; opt[1 .. $]) { 
    456                         newopt = "-" ~ c; 
     467                    opt32 = toUTF32(opt[1 .. $]); 
     468                    foreach (j, c; opt32) { 
     469                        newopt = toUTF8("-" ~ [c]); 
    457470                        match = matches(newopt); 
    458471                        if (match is null) { 
     
    462475                            // This is the last char in the group, look to the 
    463476                            // next element of args for the arg. 
    464                             if (j == opt.length-2) { 
     477                            if (j == opt32.length-1) { 
    465478                                if (i == args.length-1) expected_arg_error(match.name); 
    466479                                arg = args[i+1]; 
     
    469482                            // the arg. 
    470483                            } else { 
    471                                 arg = opt[j+2 .. $]
     484                                arg = toUTF8(opt32[j+1 .. $])
    472485                                match.perform_action(this, options, arg); 
    473486                                break; 
     
    478491                        match.perform_action(this, options, arg); 
    479492                    } 
     493                } else { 
     494                    unknown_opt_error(opt); 
    480495                } 
    481496            } else { 
     
    548563        char[][] shortopts; 
    549564        char[][] longopts; 
     565        dchar[] opt; 
    550566        Option option; 
    551         foreach (opt; options) { 
     567        foreach (_opt; options) { 
     568            // (Unicode note: We convert to dchar[] so the length checks work 
     569            // out in the event of a short opt with a >127 character.) 
     570            opt = toUTF32(_opt); 
    552571            if (opt.length < 2) { 
    553572                throw new OptionError( 
    554                     "invalid option string '" ~ opt ~ "': must be at least two characters long" 
     573                    "invalid option string '" ~ _opt ~ "': must be at least two characters long" 
    555574                ); 
    556575            } else if (opt.length > 2) { 
    557576                if (opt[0 .. 2] != "--" || opt[2] == '-') 
    558577                    throw new OptionError( 
    559                         "invalid long option string '" ~ opt ~ "': must start with --, followed by non-dash" 
     578                        "invalid long option string '" ~ _opt ~ "': must start with --, followed by non-dash" 
    560579                    ); 
    561                 longopts ~= opt; 
     580                longopts ~= _opt; 
    562581            } else { 
    563582                if (opt[0] != '-' || opt[1] == '-') 
    564583                    throw new OptionError( 
    565                         "invalid short option string '" ~ opt ~ "': must be of the form -x, where x is non-dash" 
     584                        "invalid short option string '" ~ _opt ~ "': must be of the form -x, where x is non-dash" 
    566585                    ); 
    567                 shortopts ~= opt; 
     586                shortopts ~= _opt; 
    568587            } 
    569588        } 
    570589        if (name is null) { 
     590            // (Unicode note: We know '-' is a single code unit, so these 
     591            // slices are okay.) 
    571592            if (longopts.length > 0) 
    572593                name = longopts[0][2 .. $];