conf

conf - my dotfiles manager
git clone git://git.alex.balgavy.eu/conf.git
Log | Files | Refs | README | LICENSE

commit cdb8b96bc6050573c3da1eb02b371f567537fb8e
parent dfff5d2c39d2163a614c0447bf269788bb3bd302
Author: Alex Balgavy <a.balgavy@gmail.com>
Date:   Fri,  7 Feb 2020 14:52:15 +0100

Refactoring and fix bug when editing incorrect mapfile

Editing should be possible even if there's an error in the mapfile.

Diffstat:
Mconf | 79++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 42 insertions(+), 37 deletions(-)

diff --git a/conf b/conf @@ -57,19 +57,19 @@ sub confirm { } # Print a message to stderr and exit -sub exit_die { +sub Die { print STDERR $_[0]."\n"; exit 1; } # Does a line contain a mapping? -sub is_map_line { +sub IsMapLine { # It's a mapping if it's not blank or a comment return ($_[0] !~ /^\s*$/ and $_[0] !~ /^\s*\#/ and $_[0] !~ /^$/) } # Parse a single map line into a standalone key-value mapping -sub parse_line { +sub ParseLine { # Split the line on colons my @mapline = split(':', $_[0]); @@ -87,18 +87,18 @@ sub parse_line { } # Parse the whole mapfile, return a reference to the key-value hash -sub parse_mapfile { +sub ParseMapfile { my (@nestdir, %mappings); my $lineno = 1; # Open up the mapfile for reading, using the handle MAP - open(MAP, "<$_[0]") or exit_die("Couldn't open the file $_[0], $!"); + open(MAP, "<$_[0]") or Die("Couldn't open the file $_[0], $!"); # While not EOF while(my $line = <MAP>) { - if (is_map_line($line)) { + if (IsMapLine($line)) { # Parse the mapline - my ($src, $dst) = @{parse_line($line)}; + my ($src, $dst) = @{ParseLine($line)}; # If top level mapping if ($src !~ /^-+/) { @@ -114,7 +114,7 @@ sub parse_mapfile { else { # If the source doesn't exist, can't map if (not -e $src) { - exit_die("error in mapfile: $src does not exist (line $lineno)"); + Die("error in mapfile: $src does not exist (line $lineno)"); } # If it does, add it as a mapping else { @@ -145,7 +145,7 @@ sub parse_mapfile { my $fullsrc = join("/", @nestdir)."/$src"; # If it doesn't exist, can't map if (not -e $fullsrc) { - exit_die("error in mapfile: $fullsrc does not exist (line $lineno)"); + Die("error in mapfile: $fullsrc does not exist (line $lineno)"); } # Otherwise, add the mapping else { @@ -163,14 +163,14 @@ sub parse_mapfile { } # Dump a hash, for debugging purposes -sub pretty_print { +sub PrettyPrint { puts "hash length: ".keys(%{$_[0]}); use Data::Dumper; print Dumper $_[0]; } # Link to a source path at a destination path -sub make_link_op { +sub MakeLinkOp { my ($src, $dst) = @_; # If the destination exists @@ -199,7 +199,7 @@ sub make_link_op { } # Remove a linked source path -sub rm_link_op { +sub RmLinkOp { my ($src, $dst) = @_; # If the destination doesn't exist, nothing to do here. @@ -222,7 +222,7 @@ sub rm_link_op { } # Check whether a link points to the config file -sub check_link_op { +sub CheckLinkOp { my ($src, $dst) = @_; if (-e $dst) { if (-l $_[1] and realpath($_[1]) eq $DOTFILES."/".$_[0]) { @@ -241,7 +241,7 @@ sub check_link_op { } # Execute a link operation on maps in ARGV -sub exec_link_op { +sub ExecLinkOp { # Retrieve the reference to map hash and the function to run my ($maps, $opref) = @_; @@ -269,34 +269,34 @@ sub exec_link_op { } # if nothing matches, fail else { - my %opnametab = (\&make_link_op => 'link', \&rm_link_op => 'unlink', \&check_link_op => 'check'); - exit_die "Error: $src_part not present in mapfile, don't know how to ".$opnametab{$opref}.'.'; + my %opnametab = (\&MakeLinkOp => 'link', \&RmLinkOp => 'unlink', \&CheckLinkOp => 'check'); + Die "Error: $src_part not present in mapfile, don't know how to ".$opnametab{$opref}.'.'; } } } } # Link command -sub link_cmd { +sub LinkCmd { # If no args, default to linking all but confirm with user if (not @ARGV and !confirm("Link all?")) { - exit_die "User cancelled."; + Die "User cancelled."; } - exec_link_op($_[0], \&make_link_op); + ExecLinkOp($_[0], \&MakeLinkOp); } # Unlink command -sub unlink_cmd { +sub UnlinkCmd { # If no args, default to unlinking all but confirm with user if (not @ARGV and !confirm("Unlink all?")) { - exit_die "User cancelled"; + Die "User cancelled"; } - exec_link_op($_[0], \&rm_link_op); + ExecLinkOp($_[0], \&RmLinkOp); } # Edit command -sub edit_cmd { +sub EditCmd { # Set a default editor value $ENV{EDITOR} ||= 'vim'; @@ -304,11 +304,11 @@ sub edit_cmd { system "$ENV{EDITOR} $MAPFILE"; } -sub check_cmd { - exec_link_op($_[0], \&check_link_op); +sub CheckCmd { + ExecLinkOp($_[0], \&CheckLinkOp); } -sub list_cmd { +sub ListCmd { puts "Mappings (from $MAPFILE), paths relative to $DOTFILES"; puts "(format: source => name_of_symlink)\n"; @@ -323,23 +323,28 @@ sub list_cmd { } # Run a subcommand based on string -sub run_subcommand { +sub RunSubcommand { # Dispatch table my %subcommands = ( - link => \&link_cmd, - unlink => \&unlink_cmd, - edit => \&edit_cmd, - list => \&list_cmd, - check => \&check_cmd + link => \&LinkCmd, + unlink => \&UnlinkCmd, + edit => \&EditCmd, + list => \&ListCmd, + check => \&CheckCmd ); # If the command isn't in the table, exit and print usage $subcommands{$_[0]} or pod2usage(2); - # Parse the file - my $mappings = parse_mapfile($MAPFILE); - # Then execute the command on the extracted mappings - $subcommands{$_[0]}->($mappings); + if ($_[0] eq 'edit') { + $subcommands{$_[0]}->(); + } + else { + # Parse the file + my $mappings = ParseMapfile($MAPFILE); + # Then execute the command on the extracted mappings + $subcommands{$_[0]}->($mappings); + } } # If no arguments, show usage @@ -347,7 +352,7 @@ scalar @ARGV > 0 or pod2usage(2); # Get the commandline options, only recognise help/manual, everything else gets sent to dispatch subroutine my ($help, $manual); -my %optctl = (help => \$help, manual => \$manual, '<>' => \&run_subcommand); +my %optctl = (help => \$help, manual => \$manual, '<>' => \&RunSubcommand); GetOptions(\%optctl, 'help|h', 'manual|man', '<>') or pod2usage(2); =head1 OPTIONS