Changes between Initial Version and Version 1 of VarNames/Script


Ignore:
Timestamp:
Feb 5, 2012 1:08:31 PM (6 years ago)
Author:
rado
Comment:

migrate wiki.mutt.org

Legend:

Unmodified
Added
Removed
Modified
  • VarNames/Script

    v1 v1  
     1'''Note''': Copy the preformatted /List of vars into a separate file.
     2Just the list, drop the intro text before the "---" line.
     3'''Preserve indention''' to distinguish between prefix (none) and varnames (spaces)!
     4Change the "manual-vars" filename (add path if necessary) in this
     5script accordingly right after the comments for $CONVFILE!!!
     6
     7Save the script between the "---" lines into a file, then make it executable and execute it:
     8{{{
     9 chmod a+x script
     10 ./script src dest
     11}}}
     12Read the '#' comments at the beginning of the script for usage and known pitfalls.
     13Feedback failures or false positives '''but only relevant parts of config''' (not all) either via eMail or MuttChannel => RadoQ.
     14
     15Just by itself you can '''only visually compare''' and search for mistakes this script might have produced
     16(by help of "diff"). Depending on the size of your config, you might miss single conversion failures.
     17If you want to be absolutely sure the converted config will still work with an updated mutt binary,
     18then you can have a look at VarNames/Test, where you're guided to build a patched binary from the source just to test whether this script here will
     19work without failure for your config. The test-binary will notice '''each and every failure''',
     20with all synonyms dropped, absolutely no safety net left.
     21Dare, have a look!
     22
     23----
     24{{{
     25#!/usr/bin/perl -w
     26###
     27# written 08 Aug 2006 by RadoQ (proofread & tested by Alain Bench)
     28#
     29# This script must be applied MANUALLY to all used config files:
     30### those separated by version as well as split up to be sourced from main file.
     31### it doesn't scan for "source" cmds to auto-convert them, but you can give 2 dirs, auto-convert all files.
     32### target-dir must exist for either dir or file as destination.
     33#
     34# This is a SIMPLE translation script that matches "set(SPC+varname)+" till EOL,
     35# its primary goal is to help stable users, but tries to please dev-users with $ expansion too, so it CAN FAIL when:
     36### you use varnames in (extremly) exotic ways (rare, see below, or $var expansion outside of "set" cmd).
     37### "alternates" is not 1st var in set cmd.
     38### it processes "#" comments, so "set ..." there is changed, too, possibly false positives.
     39### comments on same line like "set ... # comment" are optionally processed: specify any 3rd arg.
     40### ==> you MUST re-check your config after execution for those cases and fix manually.
     41#
     42# You MAY try to apply it to SHELL-scripts which PRODUCE muttrc config, BUT this is NOT 100% SAFE:
     43### This means SHELL-scripts called before mutt to prepare config, or from within mutt in `` substitutions or "source ...|".
     44### It works only with complete muttrc "set" cmds, it fails if only parts of "set" args are `` subst'ed.
     45#
     46# It has SIMPLE string skipping code, but it's no 100% safe muttrc parser:
     47### it might fail or produce false positives for string values with many varying quotes per assignment (rare).
     48
     49use strict;
     50
     51my $CONVFILE= 'manual-vars';    ### location of conversion source file, originally copied from /List
     52my $LINECONT= ':LINECONT:';     ### place-holder for \\\n line-continuation, must NOT appear naturally in muttrc,
     53                                ### must NOT contain muttrc special chars like #=;\n or quote-chars
     54my $PATCHFILE='/dev/null';      ### where the conversion list will be saved to be used with /Test script to patch init.h.
     55
     56my ($hits, $total, $changed) = (0,0, 0);
     57my %trans;
     58my $STOPCOMMENTS= (@ARGV < 3);
     59
     60sub replace($) {
     61my ($match) = @_;
     62my @tokens = split(/\b/,$match);
     63my ($prev,$value);
     64($prev,$value) =('','');
     65
     66ITEM:
     67        foreach $match (@tokens) {
     68        if ($match =~ /\W/) {
     69                if ($value =~ /=(["'`])/ ) {
     70                my $quote=$1 ;
     71                        if ( $match =~ /$quote/ ) {
     72                                $value=$match;
     73### necessary to avoid values being treated as keywords, remember it's RHS by keeping "=" when string not closed
     74                                if ($STOPCOMMENTS && ($match =~ /$quote.*#/ )) { last ITEM; }
     75### necessary to avoid comments after "set" being treated as keywords
     76                        }
     77                } else {
     78                        $value=$match;
     79                        if ($STOPCOMMENTS && ($match =~ /^[^=]*#/ )) { last ITEM; }
     80### necessary to avoid comments after "set" being treated as keywords, but ignore in strings
     81                }
     82
     83        } elsif ((($value !~ /=/ ) && ($prev !~ /;/)) || ($prev =~ /\$$/ )) {
     84                $match =~ /^(no|inv)*(.*)$/;
     85                my ($ctrl,$stripped) = ($1,$2);
     86                if (exists($trans{$stripped})) {
     87                        $hits++; if (!defined($ctrl)) { $ctrl='';}
     88                        $match = $ctrl . $trans{$stripped};
     89                }
     90        } # if
     91                $prev=$match;
     92        } # foreach
     93        $match = join('',@tokens);
     94        return $match;
     95} # sub
     96
     97### read whole files as single line
     98undef $/;
     99
     100### setup conversion table
     101open(CONVLIST, "<$CONVFILE") || die("Can't open conversion file $CONVFILE.");
     102my $TABLE = <CONVLIST>;
     103close(CONVLIST);
     104
     105my $prefix='';
     106
     107### for the patch
     108open(TRANSLIST,">$PATCHFILE") || die "Can't open file $PATCHFILE to save translation list for init.h patch";
     109print TRANSLIST "====== unchanged vars ======\n";
     110
     111### construct trans-table
     112my $line;
     113LINE:
     114foreach $line (split(/\n+/,$TABLE)) {
     115        if ($line =~ /^(\S+)/) { $prefix = $1; next LINE; }
     116        my (@pair) = split(/[\s(,)]+/, $line);  ### drop meta chars like () from new name
     117        my ($src,$dst) = @pair[1..2];
     118        if (!defined($dst)) { $dst='';}
     119if ($dst =~ /-/) { $dst=''; }   ### print STDERR "$src has only comment\n";
     120        if (!$dst) { $dst = $src; }
     121        $dst =~ s,^(${prefix}_)+,,;     ### no multi prefix
     122        $dst=$prefix.'_'.$dst;
     123        if ($dst ne $src) { $trans{$src}=$dst; }
     124### for the patch
     125else { print TRANSLIST "$src\n";}
     126}
     127
     128### for the patch
     129print TRANSLIST "\n====== now the conversions ======\n";
     130foreach my $item (sort keys %trans) { print TRANSLIST "$item : $trans{$item}\n"; }
     131close(TRANSLIST);
     132
     133### HERE BEGINS THE ACTUAL WORK ###
     134
     135if (@ARGV < 2) { die("Need destination file, will not replace files."); }
     136
     137my @SOURCES;
     138my ($SRCFILE, $NEWFILE);
     139my ($SRCDIR,$NEWDIR) = @ARGV;
     140if (-d $SRCDIR) {
     141        if (! -d $NEWDIR) { die("When source is a dir, then destination must be dir, too!");}
     142        opendir(DIR, $SRCDIR);
     143        @SOURCES = grep { $_ !~ /^(\.\.?)$/ } readdir( DIR);
     144        closedir(DIR);
     145        $SRCDIR.="/";
     146        $NEWDIR.="/";
     147} else { @SOURCES = ($SRCDIR); $SRCDIR='';}
     148
     149my $file;
     150FILE:
     151foreach $file (@SOURCES) {
     152($SRCFILE, $NEWFILE) = ("$SRCDIR$file","$NEWDIR");
     153
     154### now slurp it in.
     155unless (open(SOURCE,"<$SRCFILE")) { warn("Can't open old config file $SRCFILE."); next FILE;}
     156my $config = <SOURCE>;
     157$config =~ s,\\\n, $LINECONT ,go;
     158close(SOURCE);
     159
     160if (-d $NEWFILE) { my $tmp=$SRCFILE; $tmp=~s,^.*/,,; $NEWFILE.="/$tmp"; }
     161$NEWFILE =~ s,//+,/,go;
     162if (-s $NEWFILE) { warn("Destination file $NEWFILE must not exist, will not replace files."); next FILE;}
     163
     164### special case: var becomes cmd.
     165$hits= ($config =~ s/(set([ \t]| $LINECONT )+)(alternates)=?/$3 /gm );
     166
     167### now the _real_ deal
     168$total = $hits + ($config =~ s/(\b(un|re)?set|toggle)([ \t]+[^\n]+)/$1 . replace($3)/gme );
     169
     170### changed type to plain boolean, no "ask-"
     171$config =~ s,(pgp_autoinline=['"]*)ask-,$1,gm;
     172
     173### save changes
     174unless (open(TARGET,">$NEWFILE")) { warn("Can't open NEW config file $NEWFILE, does dir exist?"); next FILE ;}
     175$config =~ s, $LINECONT ,\\\n,go;
     176print TARGET $config;
     177close(TARGET);
     178
     179printf STDERR "changed vars: %3s in checked lines: %3d in $NEWFILE\n", $hits, $total;
     180
     181$changed+=$hits;
     182
     183} # foreach SOURCES, FILE
     184
     185if ($changed) {
     186print STDERR "Total $changed changes. Please verify excess or missing changes!!! Use this cmd:\n";
     187if ($#SOURCES < 1) {
     188        print STDERR "\tsdiff $SRCFILE $NEWFILE| less +'/ \\| '\n";
     189} else {
     190        print STDERR "\tdiff -r $SRCDIR $NEWDIR| less +'/^diff.*'\n";
     191}
     192}
     193
     194### EOF
     195}}}