/* * [Rep.java] * * Summary: Regex Search and Replace. * * Copyright: (c) 2014-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2014-11-21 initial version */ package com.mindprod.rep; import com.mindprod.common18.EIO; import com.mindprod.hunkio.HunkIO; import java.io.File; import java.io.IOException; import java.util.Arrays; import static java.lang.System.*; /** * Regex Search and Replace. *

* Bulk search/replace with regexes or plain strings. * You provide anScript implementation to define which files to process and which replacements to make. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2014-11-21 initial version * @since 2014-11-21 */ public class Rep { // declarations private static final int FIRST_COPYRIGHT_YEAR = 2014; private static final boolean DEBUGGING = false; /** * non-displaying copyright. * * @noinspection UnusedDeclaration */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 2014-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; private static final String RELEASE_DATE = "2014-11-22"; private static final String TITLE_STRING = "Regex Search/Replace"; private static final String USAGE = "rep.jar SomeScript [filenames]"; private static final String VERSION_STRING = "1.0"; /** * Script class with ScriptItems and files to process */ private static Script script; // /declarations // methods /** * dynamically load the Script configuration */ private static void hookConfiguration( String configurationName ) { // effectively something like: script = new UntidyScript(); try { // e.g. parm to Class.forName looks like: "ConfigurationForMindprod" final String binaryClassName = "com.mindprod.rep." + configurationName; // Make sure the class we dynamically load implements the Configuration interface. final Class scriptClass = Class.forName( binaryClassName ).asSubclass( Script.class ); script = scriptClass.newInstance(); } catch ( ClassCastException e ) { // configuration exists but is screwed up, but the code exists. throw new ClassCastException( "Coding bug: The code to process configuration " + configurationName + " refused access. It needs a public no-arg constructor." ); } catch ( Exception e ) { // might have been ClassNotFoundException, NoClassDefFoundException // Any problem is a failure. err.println( "Fatal error: Configuration " + configurationName + " not found" ); System.exit( 2 ); } } // /method /** * main * * @param args first parm is name of User Script class. User defines rest of parms. */ public static void main( String[] args ) { if ( args.length < 1 ) { throw new IllegalArgumentException( USAGE ); } hookConfiguration( args[ 0 ] ); int fileChangeCount = 0; int fileCount = 0; try { for ( File file : script.allFilesToProcess( Arrays.copyOfRange( args, 1, args.length ) ) ) { fileCount++; final String original = HunkIO.readEntireFile( file ); String modified = original; for ( ScriptItem si : script.allScriptItems() ) { modified = si.doReplacements( modified ); } // have done all script items for a file. if ( !modified.equals( original ) ) { fileChangeCount++; out.println( "* " + EIO.getCanOrAbsPath( file ) ); // write and rename to provide extra safety from crash final File tempFile = HunkIO.createTempFile( "temp_", ".tmp", file ); HunkIO.writeEntireFile( tempFile, modified ); // successfully created output in same directory as input, // Now make it replace the input file. HunkIO.deleteAndRename( tempFile, file ); } } } catch ( IOException e ) { err.println( "IOException: " + e.getMessage() ); System.exit( 1 ); } if ( DEBUGGING ) { // report any Script items not found: for ( ScriptItem si : script.allScriptItems() ) { if ( !si.isUsed() ) { err.println( "u n u s e d: " + si.toString() ); } } } out.println( fileCount + " files processed. " + fileChangeCount + " files changed." ); } // /method // /methods }