--- loncom/ConfigFileEdit.pm 2003/11/25 12:09:57 1.1 +++ loncom/ConfigFileEdit.pm 2003/12/02 12:06:25 1.2 @@ -26,6 +26,8 @@ package ConfigFileEdit; +use IO::File; + # # Module to read/edit configuration files. # See the POD at the bottom of the file for more information. @@ -239,24 +241,25 @@ sub DeleteLine { my $lastidx = $self->LineCount() - 1; # Index of last item. - my @temp = @$lines; - + my @temp; if(! defined($index->{$key})) { # bail if no match. return; } my $itemno = $index->{$key}; # Index of item to delete. + if ($itemno != $lastidx) { # need to slide and reindex. - @$temp[$itemno..($lastidx-1)] = - @$temp[$itemno+1..$lastidx]; - $#temp = $lastidx - 1; - $self->{KeyToLines} = Index(\@temp, $self->{Indexfield}); + @temp = @$lines[0..($itemno-1)]; + @temp[$itemno..($lastidx-1)] = @$lines[($itemno+1)..$lastidx]; + + } else { # just need to truncate - $#temp = $lastidx-1; # the line array... - delete($index->{$key}); # and remove from index hash. + @temp = @$lines[0..$lastidx-1]; # So take the initial slice. } - $self->{LineArray} = \@temp; + + $self->{KeyToLines} = Index(\@temp, $self->{Indexfield}); + $self->{LineArray} = \@temp; # Replace the lines index. } @@ -294,5 +297,176 @@ sub ReplaceLine { } } } +# +# Write the configuration array to a file: +# Parameters: +# $self - Reference to the object's member data hash. +# $fh - Name of file to write. +sub Write { + my $self = shift; + my $fh = shift; + + my $lines = $self->{LineArray}; + my $length = @$lines; + for (my $i = 0; $i < $length; $i++) { + print $fh $lines->[$i]."\n"; + } +} + 1; +#----------------------------- Documentation -------------------------------------- +# + +=pod + +=head1 NAME + +ConfigFileEdit - Lookups and edits on a configuration file. + +=head1 SYNOPSIS + + use LONCAPA::ConfigFileEdit; + use IO::File; + + my $editor = ConfigFileEdit->new("file.cfg", 0); + $editor->Append("new:line:with:config:info"); + my $line = $editor->Find("key"); + my $size = $editor->LineCount(); + $editor->DeleteLine("george"); + $editor->ReplaceLine("new","new:line:with:different:info"); + my $fh = new IO::File("> modified.cfg", 0); + $editor->Write($fh); + +=head1 DESCRIPTION + +Configuration files in LonCAPA contain lines of colon separated fields. +Configuration files can also contain comments initiated by the hash (#) +character that continue to the end of line. Finally, configuration files +can be made more readable by the inclusion of either empty lines or +lines entirely made up of whitespace. + +ConfigFileEdit allows manipulation of configuration files in a way that +preserves comments and order. This differs from LonCAPA's 'normal' mechanism +handling configuration files by throwing them up into a hash by key. + +ConfigFileEdit maintains the original configuration file in an array and +creates the index hash as a hash to line numbers in the array. This allows +O(k) time lookups, while preserving file order and comments (comments are +lines in the array that have no indices in the associated hash. + +In addition to line lookup, ConfigFileEdit supports simple editing +functions such as delete, append, and replace. At present, Insertions +at arbitrary points in the file are not supported. The modified +file can also be written out. + +=head1 METHODS + +=head2 new ( filename, keyfield ) + +Creates a new ConfigFileEdit object from an existing file. Where: + +=over 4 + +=item * filename - The name of the configuration file to open. + +=item * keyfield - The number of the field for which the index hash is generated. + Fields are enumerated from zero. + +=item * RETURNS: - undef if the file could not be open, otherwise a reference + to a hash that contains the object member data. + +=back + +=head2 Append ( newline ) + +Appends a new line to the configuration file in memory. The file that was +used to create the object is not modified by this operation. + +=over 4 + +=item * newline - A new line to append to the end of the configurationfile. + +=back + +=head2 LineCount + +Returns the number of lines in the file. This count includes the nubmer of +comments. + +=head2 DeleteLine ( key ) + +Deletes the line that matches key. Note that if there is no matching line, +this function is a no-op. + +=over 4 + +=item * key - The key to match, the line that is indexed by this key is deleted. + +=back + +=head2 ReplaceLine ( key, newcontents ) + +Replaces the selected line in its entirety. Note that the config file is re-indexed +so it is legal to modify the line's key field. + +=over 4 + +=item * key - The key that selects which line is replaced. + +=item * newcontents - The new contents of the line. + +=back + +=head2 Write ( fh ) + +Writes the contents of the configuration file's line array to file. + +=over 4 + +=item * fh - A file handle that is open for write on the destination file. + +=back + +=head2 Comment ( line ) + +Static member that returns true if the line passed in is a comment or blank line. + +=head2 Field ( line, index ) + +Static member that returns the value of a particular field on a config file line. + +=over 4 + +=item * line - The line that's parsed. + +=item * index - The index requested (0 is the first field on the line). + +=back + +=head2 Index ( linearray, fieldno ) + +Returns a reference to a hash that indexes a line array by a particular field number. +this can be used to produce secondary indices if required by the application (see +MEMBER DATA below). + +=over 4 + +=item * linearray - A reference to an array containing text in configuration file format. +=item * fieldno - Number of the field to index (0 is the first field). + +=item * RETURNS - A reference to a hash from field value to line array element number. + +=back + +=head1 MEMBER DATA + +The following member data can be considered exported. + +=head2 LineArray + +The reference to the configuration files line array. + +=cut + +__END__