moved nonpb.pm
[PsN.git] / lib / model / problem / record_subs.pm
blob55d820d605885fe63e078cddcec82f17f5ab2ab5
1 # {{{ new
2 start new
4 # To construct an option you inly need to suply an array of
5 # strings containg the record block. _read_option then parses
6 # those strings.
7 $this -> _read_options;
8 delete $this -> {'record_arr'};
10 end new
11 # }}}
13 # {{{ option_count
15 start option_count
17 # record::option_count returns the number of options of the
18 # record.
20 $return_value = 0;
21 if( defined $self -> {'options'} )
22 $return_value += @{$self -> {'options'}};
24 end option_count
26 # }}}
28 # {{{ remove_option
30 start remove_option
32 my @options = @{$self -> {'options'}};
33 my @new_options = ();
34 foreach my $option ( @options ) {
35 next if ( $option -> name eq $name );
37 next if ( $fuzzy_match and index( $name, $option -> name ) > -1 );
39 push( @new_options, $option );
41 $self -> {'options'} = \@new_options;
42 end remove_option
44 # }}} remove_option
46 # {{{ _add_option
47 start _add_option
49 # Create a new option. $option_string should be of the form
50 # "option=value". TODO catch any error from below.
51 my $opt_obj =
52 model::problem::record::option -> new ( option_string => $option_string );
53 push( @{$self -> {'options'}}, $opt_obj ) if( $opt_obj );
55 end _add_option
56 # }}}
58 # {{{ _read_options
60 start _read_options
63 # record::_read_options
66 # This is a tricky method that parses options. The basic parsing
67 # is real easy, it loops over the records strings, for each
68 # string it looks for options of the form "option=value" or
69 # "option", those substrings are then used to creat options. But
70 # while the parser does this it keeps count of the number of
71 # options it has parsed, and pushes it on the "print_order"
72 # array (which has a bit missleading name) when it finds a
73 # comment. This is then used to remember where comments appear
74 # in the NONMEM modelfile. Unfortunataly this only holds for
75 # ordinary records, code records are cut verbatim from the
76 # modelfile, so they will also have their comments in place, but
77 # init records will loose any comments associated with them.
79 # TODO This is a hack, I admit, a nicer way would be to store
80 # comments with the option it was found near and defer
81 # formatting to the option class.
83 my @row = ();
84 my $order = 0;
86 # Loop over all given strings.
87 for( my $i = 0; $i <= $#{$self -> {'record_arr'}}; $i++ ) {
88 # Store it in $_ for all string matching to look nice
89 $_ = $self -> {'record_arr'} -> [$i];
91 if( /^\s*(\;.*)$/ ) {
92 # This is a comment on a line of its own.
93 if( $order == 0 ){
94 push(@{$self -> {'comment'}}, $1 . "\n");
95 } else {
96 push(@{$self -> {'comment'}},"\n" . $1 . "\n");
98 # Record after which option the comment appeared.
99 push( @{$self -> {'print_order'}}, $order );
100 } else {
101 # Get rid of $RECORD
102 s/^\s*\$\w+//;
103 # remove spaces near '=' and ','
104 s/\s*([\=\,])\s*/$1/g;
105 # remove spaces near paranthesis
106 s/\s*\)/\)/g;
107 s/\(\s*/\(/g;
109 # Find trailing comments.
110 my $comment;
111 if( /(\;.*)$/ ) {
112 # We find comments here, but we add it to 'the comment'
113 # member after we have parsed all options. Only so we can
114 # now how many options we found.
116 $comment = ' ' . $1 . "\n";
117 # Get rid of trailing comments
118 s/\;.*$//g;
120 @row = split;
121 for ( @row ) {
122 # Create options.
123 $self -> _add_option( option_string => $_ );
124 $order++;
126 if( length( $comment ) > 0 ) {
127 # This is a comment at the end of a line.
128 push( @{$self -> {'comment'}},' ' . $1 . "\n" );
129 push( @{$self -> {'print_order'}}, $order );
134 end _read_options
136 # }}}
138 # {{{ _format_record
139 start _format_record
142 # record::format_record
145 # This method might be even more trickier than _read_options,
146 # but don't worry, I'll walk you through it. You should read
147 # the comments in _read_options first though, it might help.
149 # Get the recordname from the class name.
150 my @class_names = split('::',ref($self));
151 my $fname = uc(pop(@class_names));
153 # Get some members from the object.
154 my @print_order = defined $self -> {'print_order'} ? @{$self -> {'print_order'}} : ();
155 my @comments = defined($self -> {'comment'}) ? @{$self -> {'comment'}} : () ;
156 my @options = defined($self -> {'options'}) ? @{$self -> {'options'}} : ();
158 # Each element of @print_order is a number which says how many
159 # options(since the previous comment was printed) that should
160 # be processed before the next comment should be
161 # printed. There will be one element in print order for each
162 # comment. So here we intialize $opts_before_comment which is
163 # the current number of options we should process. If
164 # $opts_before_comment is -1 no more comments will be expected
165 # nor printed.
167 my $opts_before_comment = scalar @print_order > 0 ? shift @print_order : -1;
169 # $last_is_option is a boolean which is true if we printed a
170 # option in the last iteration of the loop below and false if
171 # we printed a comment. It is used to see if we need to print
172 # an extra "\n" since comments is expected to have their own
173 # "\n" while options don't
175 my $last_is_option = 1;
176 my $line = 0;
178 # Loop over all options. Actually we loop one step to long,
179 # since we might have comments after the last option.
180 for( my $i = 0; $i <= scalar @options; $i++ ){
182 # See if we have processed enough options to print
183 # commments. It is a loop since we might have multiple lines
184 # of comments.
185 while( $i == $opts_before_comment ){
186 my $comment = shift(@comments);
187 # Check and add a linebreak if necessarry.
188 if ( length( $formatted[$line].' '.$comment ) > 70 ) {
189 $formatted[$line] .= "\n";
190 $line++;
192 # add the comment
193 $formatted[$line++] .= $comment;
195 # If we expect more options ($i <= $#options) and we have
196 # printed the recordname ($i > 0) we indent before
197 # printing the next option.
198 if( $i <= $#options and $i > 0 ){
199 $formatted[$line] .= ' ' x 11;
202 if( scalar @print_order > 0 ) {
203 $opts_before_comment = shift @print_order;
204 } else {
205 unless( scalar @comments > 0 ){
207 # If we have more comments, it likely mean that
208 # someone has appended comments manually. TODO This
209 # might become a mess and we should probably add a
210 # feature to add commments before or after the record.
212 $opts_before_comment = -1;
216 $last_is_option = 0;
219 # Print the record name (with indentation)
220 if( $i == 0 ){
221 push( @formatted , "\$".$fname . ' ' x (10 - length($fname)) );
224 # Check that we have not processed all options.
225 if( $i <= $#options ){
226 my $option = $options[$i];
227 # Let the option class format the option.
228 my $foption = $option -> _format_option;
230 # Check and add linebreak if necesary.
231 if ( length( $formatted[$line].' '.$foption ) > 70 ) {
232 $formatted[$line] .= "\n";
233 $line++;
234 # Indent for next option
235 push( @formatted, ' ' x 11 );
238 $formatted[$line] .= ' '.$foption;
239 $last_is_option = 1;
243 # Print a line break if the last item was an option (as oposed
244 # to a comment.
245 if( $last_is_option ){
246 $formatted[$line] .= "\n";
249 end _format_record
250 # }}}