Robochameleon  v1.0
parseArgs.m
1 function ArgStruct=parseArgs(args,ArgStruct,varargin)
2 % Helper function for parsing varargin.
3 %
4 %
5 % ArgStruct=parseArgs(varargin,ArgStruct[,FlagtypeParams[,Aliases]])
6 %
7 % * ArgStruct is the structure full of named arguments with default values.
8 % * Flagtype params is params that don't require a value. (the value will be set to 1 if it is present)
9 % * Aliases can be used to map one argument-name to several argstruct fields
10 %
11 %
12 % example usage:
13 % --------------
14 % function parseargtest(varargin)
15 %
16 % %define the acceptable named arguments and assign default values
17 % Args=struct('Holdaxis',0, ...
18 % 'SpacingVertical',0.05,'SpacingHorizontal',0.05, ...
19 % 'PaddingLeft',0,'PaddingRight',0,'PaddingTop',0,'PaddingBottom',0, ...
20 % 'MarginLeft',.1,'MarginRight',.1,'MarginTop',.1,'MarginBottom',.1, ...
21 % 'rows',[],'cols',[]);
22 %
23 % %The capital letters define abrreviations.
24 % % Eg. parseargtest('spacingvertical',0) is equivalent to parseargtest('sv',0)
25 %
26 % Args=parseArgs(varargin,Args, ... % fill the arg-struct with values entered by the user
27 % {'Holdaxis'}, ... %this argument has no value (flag-type)
28 % {'Spacing' {'sh','sv'}; 'Padding' {'pl','pr','pt','pb'}; 'Margin' {'ml','mr','mt','mb'}});
29 %
30 % disp(Args)
31 %
32 %
33 %
34 %
35 % % Aslak Grinsted 2003
36 
37 Aliases={};
38 FlagTypeParams='';
39 
40 if (length(varargin)>0)
41  FlagTypeParams=strvcat(varargin{1});
42  if length(varargin)>1
43  Aliases=varargin{2};
44  end
45 end
46 
47 
48 %---------------Get "numeric" arguments
49 NumArgCount=1;
50 while (NumArgCount<=size(args,2))&(~ischar(args{NumArgCount}))
51  NumArgCount=NumArgCount+1;
52 end
53 NumArgCount=NumArgCount-1;
54 if (NumArgCount>0)
55  ArgStruct.NumericArguments={args{1:NumArgCount}};
56 else
57  ArgStruct.NumericArguments={};
58 end
59 
60 
61 %--------------Make an accepted fieldname matrix (case insensitive)
62 Fnames=fieldnames(ArgStruct);
63 for i=1:length(Fnames)
64  name=lower(Fnames{i,1});
65  Fnames{i,2}=name; %col2=lower
66  AbbrevIdx=find(Fnames{i,1}~=name);
67  Fnames{i,3}=[name(AbbrevIdx) ' ']; %col3=abreviation letters (those that are uppercase in the ArgStruct) e.g. SpacingHoriz->sh
68  %the space prevents strvcat from removing empty lines
69  Fnames{i,4}=isempty(strmatch(Fnames{i,2},FlagTypeParams)); %Does this parameter have a value? (e.g. not flagtype)
70 end
71 FnamesFull=strvcat(Fnames{:,2});
72 FnamesAbbr=strvcat(Fnames{:,3});
73 
74 if length(Aliases)>0
75  for i=1:length(Aliases)
76  name=lower(Aliases{i,1});
77  FieldIdx=strmatch(name,FnamesAbbr,'exact'); %try abbreviations (must be exact)
78  if isempty(FieldIdx)
79  FieldIdx=strmatch(name,FnamesFull); %&??????? exact or not?
80  end
81  Aliases{i,2}=FieldIdx;
82  AbbrevIdx=find(Aliases{i,1}~=name);
83  Aliases{i,3}=[name(AbbrevIdx) ' ']; %the space prevents strvcat from removing empty lines
84  Aliases{i,1}=name; %dont need the name in uppercase anymore for aliases
85  end
86  %Append aliases to the end of FnamesFull and FnamesAbbr
87  FnamesFull=strvcat(FnamesFull,strvcat(Aliases{:,1}));
88  FnamesAbbr=strvcat(FnamesAbbr,strvcat(Aliases{:,3}));
89 end
90 
91 %--------------get parameters--------------------
92 l=NumArgCount+1;
93 while (l<=length(args))
94  a=args{l};
95  if ischar(a)
96  paramHasValue=1; % assume that the parameter has is of type 'param',value
97  a=lower(a);
98  FieldIdx=strmatch(a,FnamesAbbr,'exact'); %try abbreviations (must be exact)
99  if isempty(FieldIdx)
100  FieldIdx=strmatch(a,FnamesFull);
101  end
102  if (length(FieldIdx)>1) %shortest fieldname should win
103  [mx,mxi]=max(sum(FnamesFull(FieldIdx,:)==' ',2));
104  FieldIdx=FieldIdx(mxi);
105  end
106  if FieldIdx>length(Fnames) %then it's an alias type.
107  FieldIdx=Aliases{FieldIdx-length(Fnames),2};
108  end
109 
110  if isempty(FieldIdx)
111  error(['Unknown named parameter: ' a])
112  end
113  for curField=FieldIdx' %if it is an alias it could be more than one.
114  if (Fnames{curField,4})
115  val=args{l+1};
116  else
117  val=1; %parameter is of flag type and is set (1=true)....
118  end
119  ArgStruct.(Fnames{curField,1})=val;
120  end
121  l=l+1+Fnames{FieldIdx(1),4}; %if a wildcard matches more than one
122  else
123  error(['Expected a named parameter: ' num2str(a)])
124  end
125 end
126