## Copyright (C) 1998 Hrvoje Niksic
## Modification by Zeljko Boros (block entries, removing old entries)
## More options and use strict by Zoran Dzelajlija on 2004-02-24
+## Quite a few improvements by Damir Dzeko on 2005-03-18 (see bellow)
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## -> reformated code, introduced coding conventions
## -> increased reliability through atomic actualization
## -> everything is done in the memory - more mem, less i/o
-## -> removed append mode - in-place editing considered harmfull
+## -> removed append mode - in-place editing considered harmful
## -> added in-place mode as option
use strict;
-r | --remove Remove entry PACKAGE from FILE.
Default is to add lines from stdin.
+ -x | --change Modify existing block, or add it if
+ it does not exist but the begin mark
+ can be found.
+
-m | --allow-multiple Allow multiple blocks of the same type.
By default, old blocks are replaced with
the new one.
-h | --help Print this message (usage reference).
-
+
--version Print version message.
- Placement control:
-i | --insert-after x Insert after this/matching line.
-f | --insert-before x Insert before this/matching line.
- -R | --regexp-match Use regexp mode for line matching.
- Manipulating block marks:
# InsertRemove modes
use constant DO_REMOVE => 0;
use constant DO_INSERT => 1;
+use constant DO_CHANGE => 2;
# Operation defaults
$InsertRemove = DO_INSERT;
$Placement = APPEND_AT_END;
+$RegexpMatch = 1;
$Comment = '#';
$CommentEnd = '';
$MatchLine = '';
elsif (/^-r$/ || /^--remove$/) {
$InsertRemove = DO_REMOVE;
}
+ elsif (/^-x$/ || /^--change$/) {
+ $InsertRemove = DO_CHANGE;
+ }
elsif (/^-m$/ || /^--allow-multi(?:ple)?$/) {
$Multi = 1;
}
$Placement = INSERT_ON_TOP;
}
elsif (/^-R$/ || /^--regexp(?:-match|-mode)?$/) {
- $RegexpMatch = 1;
+ $RegexpMatch = 1; # it's the default
}
elsif (/^-h$/ || /^--help$/) {
die $UsageLong;
unshift(@ARGV, $_);
last;
}
+
+ if ($Multi and DO_CHANGE == $InsertRemove) {
+ die "$ProgramName: Cannot use both `--change' and `--allow-multiple'\n";
+ }
}
$Package = shift or die $UsageShort;
sub do_it {
slurp();
- if (DO_INSERT == $InsertRemove) {
+ if (DO_CHANGE == $InsertRemove) {
+ $StdinContent = &stdin_content;
+ change() or add();
+ }
+ elsif (DO_INSERT == $InsertRemove) {
$StdinContent = &stdin_content;
del() unless $Multi;
add();
return scalar(@Lines); # whatever
}
+sub change() {
+ my ($mytrailer, $mybegin, $myend) =
+ ($Trailer, $MarkBegin, $MarkEnd);
+
+ my ($bm_found, $em_found); # begin/end mark found indicator
+
+ # Make the strings regexp-friendly by quoting non-word chars.
+ $mybegin =~ s/\W/\\$&/g;
+ $myend =~ s/\W/\\$&/g;
+ $mytrailer =~ s/\W/\\$&/g;
+
+ my (@filtered, $done, $skip);
+ $done = 0; # job done once
+ $skip = 0; # skip original block
+ foreach (@Lines) {
+ if (! $done and $skip > 0) {
+ if (/^$myend(?:$mytrailer)?$/o) {
+ ++ $done; # skipped all that was to skip
+ } else {
+ ++ $skip; # count lines being skipped
+ }
+ }
+ elsif (0 == $skip and $_ =~ /^$mybegin(?:$mytrailer)?$/o) {
+ push (@filtered, $StdinContent);
+ $skip = 1;
+ }
+ else {
+ push (@filtered, $_)
+ }
+ # for safety check:
+ $bm_found = 1 if (/^$mybegin(?:$mytrailer)?$/o);
+ $em_found = 1 if (/^$myend(?:$mytrailer)?$/o);
+ }
+ if ($bm_found and $em_found) {
+ -- $skip; # correct the counter
+ DEBUG and print STDERR "Replaced block of $skip lines\n";
+ @Lines = @filtered;
+ }
+ elsif ($bm_found and ! $em_found) {
+ # safety exit
+ die "$ProgramName: no end-mark after begin-mark!\n";
+ }
+ return $done;
+}
+
# written by ddzeko@srce.hr, 2005-03-18
# to improve reliabilitah :)
#