Code archives/File Utilities/Semi-automatic 2 variable replacement tool
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This utility goes through all files/folders in a directory, and checks if they're using the extensions specified. It then looks through each line of the file(s) it finds, and replaces all code meeting the specified criteria. In my situation, it'll replace all instances of ListAddLast(List, Object), with List.AddLast(Object). It's a bit limited, but pretty functional if you ask me. Extra information: This code will automatically generate a configuration file for you, so don't bother making one. All you'll need to do is edit the file it generates. Feel free to post your thoughts on this tool, and please report any bugs you find. This software is provided as-is, I do not take any responsibility for any damage it may cause. | |||||
' The backstory(Look ahead for the actual code): Rem A little while back I started working on a game in BlitzMax, I worked on it with full intent of porting it to Monkey later down the road. However, I used the ListAddLast command, which doesn't work in Monkey the same way. As far as I know, it's not possible to make a wrapper for this, so I decided to convert those bits from my Blitz Max code. Instead of doing it myself, I made this: End Rem ' Enable strict or SuperStrict SuperStrict ' Framework Framework BRL.Blitz ' Imports: Import BRL.Stream Import BRL.StandardIO Import BRL.FileSystem Import BRL.Retro Import BRL.PolledInput ' Globals: Global ConsoleOutput:Byte = True ' Start the program Main() ' The main program Function Main:Int() ' Read our configuration file(If it doesn't exist, it'll be created) Local ConfigData:String[] = ReadConfig("config.txt") ' Define our original data's string: Local Data:String = ConfigData[0] ' Define our new data's string: Local NewData:String = ConfigData[1] ' Define our location data: Local Files:String = ConfigData[2] Local _Files:String[] ' Check to see if our Files variable is set to the AppArgs: If (Upper(Files) = "APPARGS") Then _Files = AppArgs Else _Files = [Files] EndIf ' Define our recursion variable, and check our recursion setting Local Recursive:Int If (Upper(ConfigData[3]) <> "FALSE" And ConfigData[3] <> "0") Then Recursive = 1 EndIf ' Create our white list object Local WhiteList:TList = New TList Local WListStr:String ' Check if we have any data coming in If (ConfigData[4] <> "") Then ' Check if we have more than one file whitelisted: If (Instr(ConfigData[4], ",")) Then ' If there's more than one file extension, then do the following: ' Repeat until we're to the last white listed file extension Repeat ' Add the calculated string to the white list: WListStr = Left(ConfigData[4], Instr(ConfigData[4], ",")-1) WhiteList.AddLast(WListStr) ' Modify ConfigData[4], so it doesn't hold the data we added to the white list. ConfigData[4] = Right(ConfigData[4], Len(ConfigData[4]) - Len(WListStr) - 1) WListStr = "" Until Not Instr(ConfigData[4], ",") ' Find our last file extension, and add it to the white list: If (ConfigData[4] <> "") Then WListStr = ConfigData[4] WhiteList.AddLast(WListStr) WListStr = "" EndIf Else ' If we only have one entry, add it to the white list. WhiteList.AddLast(ConfigData[4]) EndIf Else ' If we didn't find anything, just add a blank string to the list. WhiteList.AddLast("") EndIf Console("Beginning search routine...") ' Grab the file(s) using the extracted config data: ReplaceFiles(_Files, Data, NewData, Recursive, True, 0, WhiteList) ' We're done, now wait for as long as needed(If ConsoleOutput is enabled): Console("Search routine finished.") If (ConsoleOutput = True) Then WaitChar() End Function Function ReadConfig:String[](Location:String) ' Create an array holding all 5 return strings Local ReturnData:String[5] ' Attempt to open a stream for the configuration. Local Stream:TStream = ReadStream(Location) ' If we can't open the stream, create the file(s) we need, then close the program: If (Not Stream) Then Stream = WriteStream(Location) Stream.WriteLine("File = AppArgs") Stream.WriteLine("Original = " + Chr(34) + "(*1, *2)" + Chr(34)) Stream.WriteLine("Replaced = " + Chr(34) + "(*2, *1)" + Chr(34)) Stream.WriteLine("Recursive = True") Stream.WriteLine("WhiteList = " + Chr(34) + "txt" + Chr(34)) CloseStream(Stream) End EndIf ' Define the needed local variables: Local InLine:String Local File:String = "AppArgs" Local Original:String = "(*1, *2)" Local Replaced:String = "(*2, *1)" Local Recursive:String = "1" Local WList:String = "txt" ' Look through each line of the file: Repeat ' Read the current line. InLine = Stream.ReadLine() ' Check if we're dealing with a setting, or unneeded text: If (Instr(InLine, "=")) Then ' Apply the settings as needed(I'm too lazy to give this section comments): If (Instr(Upper(InLine), "FILE") Or Instr(Upper(InLine), "FILES")) Then File = Right(InLine, Len(InLine) - Instr(InLine, "=")) If (Instr(File, Chr(34))) Then File = Right(File, Len(File) - Len(Left(File, Instr(File, Chr(34))-1))) File = Replace(File, Chr(34), "") Else File = "AppArgs" EndIf EndIf If (Instr(Upper(InLine), "ORIGINAL")) Then Local _Original:String = Right(InLine, Len(InLine) - Instr(InLine, "=")) If (Instr(_Original, Chr(34))) Then Original = _Original Original = Right(Original, Len(Original) - Len(Left(Original, Instr(Original, Chr(34))-1))) Original = Replace(Original, Chr(34), "") Else RuntimeError("Please use quotes on 'Original' & Replaced") EndIf EndIf If (Instr(Upper(InLine), "REPLACED")) Then Local _Replaced:String = Right(InLine, Len(InLine) - Instr(InLine, "=")) If (Instr(_Replaced, Chr(34))) Then Replaced = _Replaced Replaced = Right(Replaced, Len(Replaced) - Len(Left(Replaced, Instr(Replaced, Chr(34))-1))) Replaced = Replace(Replaced, Chr(34), "") Else RuntimeError("Please use quotes on 'Replaced' & Original") EndIf EndIf If (Instr(Upper(InLine), "RECURSIVE")) Then Recursive = Right(InLine, Len(InLine) - Instr(InLine, "=")) Recursive = Replace(Recursive, " ", "") Recursive = Replace(Recursive, Chr(34), "") EndIf If (Instr(Upper(InLine), "WHITELIST")) Then If (Instr(InLine, Chr(34))) Then WList = Right(InLine, Len(InLine) - Instr(InLine, "=")) WList = Right(WList, Len(WList) - Instr(WList, Chr(34))) WList = Replace(WList, Chr(34), "") WList = Replace(WList, " ", "") Else RuntimeError("Please use quotes with the white list. Example: " + Chr(34) + "txt, xml" + Chr(34)) EndIf EndIf EndIf InLine = "" Until Stream.Eof() ' Close the configuration file's stream CloseStream(Stream) ' Assign each ID in array to the needed information: ReturnData[0] = Original ReturnData[1] = Replaced ReturnData[2] = File ReturnData[3] = Recursive ReturnData[4] = WList ' Return the array: Return ReturnData End Function Function ReplaceFiles:Int(S:String[], Data:String, NewData:String, Recursive:Int=1, SkipDots:Byte=True, Branch:Int=0, WhiteList:TList=Null) ' A boolean used to check if we've found a file. Local FileFound:Byte = False ' The number of files found. Local FileCount:Int = 0 For Local File:String = EachIn S ' If we found nothing, this file, or another EXE file, continue. If (File = AppFile Or File = "" Or Right(Lower(File), 4) = ".exe") Then Continue ' Check if the file/directory/other exists: If (FileType(File) <> 0) Then ' Select the file type of the 'File': Select FileType(File) Case FILETYPE_FILE ' 1 ' Run the ReplaceData function, and if it isn't false, set the FileFound variable to true, and add to the file-count: If (ReplaceData(File, Data, NewData, WhiteList)) Then FileFound = True FileCount :+ 1 EndIf Default ' FILETYPE_DIR ' Check for recursion:s If (Recursive = 1 Or Recursive = 0) Then ' Nothing to see here: If (Branch <> 0) Then Console("Branching to more directories... (Branch " + (Branch+1) + " -> Branch " + (Branch+2) + ")") Else Console("Branching to more directories... (Origin -> Branch " + (Branch+1) + ")") Console("Branching to more directories... (Branch " + (Branch+1) + " -> Branch " + (Branch+2) + ")") EndIf ' Run this command again: ReplaceFiles(LoadDir2(File, SkipDots), Data, NewData, 1-Recursive, SkipDots, Branch+1, WhiteList) EndIf End Select EndIf Next If (Branch <> 0) Then Console("") Console("Branch " + (Branch+1) + "'s results:") Else Console("") Console("First search branch's results:") EndIf If (FileFound = True) Then If (FileCount <> 1) Then Console(FileCount + " files have been found.") Else Console("Only " + FileCount + " file was found.") EndIf Else Console("No files were found...") EndIf Console("") If (Branch <> 0) Then Console("(Branch " + (Branch+1) + " -> Branch " + (Branch) + ")") Else Console("(Branch " + (Branch+1) + " -> Origin)") EndIf End Function ' Decided to add to the LoadDir command for the recursion system: Function LoadDir2:String[](File:String, SkipDots:Byte=True) If (Right(File, 1)<>"/" Or Right(File, 1)<>"\") Then If (Instr(File, "/")) Then File :+ "/" ElseIf (Instr(File, "\")) Then File :+ "\" EndIf EndIf Local Dir:String[] = LoadDir(File, SkipDots) Local ID:Int For Local S:String = EachIn Dir Dir[ID] = File + S ID :+ 1 Next Return Dir End Function Function ReplaceData:Byte(File:String, Data:String, NewData:String, WhiteList:TList=Null) ' Start our in and out streams: ' Nothing to see here: If (WhiteList) Then Local WListResponse:Byte For Local WListString:String = EachIn WhiteList If (WListString <> "") Then If (Left(WListString, 1) = ".") Then If (Instr(File, WListString)) Then WListResponse = True Exit EndIf Else If (Instr(File, "." + WListString)) Then WListResponse = True Exit EndIf EndIf Else WListResponse = True Exit EndIf Next If (WListResponse = False) Then Return False EndIf ' Open the 'InStream' for our file: Local InStream:TStream = ReadStream(File) If (Not InStream) Then RuntimeError("Unable to open '" + File + "'") ' If this file has "_Replaced" in it, skip it. If (Instr(File, "_Replaced")) Then CloseStream(InStream) ; Return False ' Open the 'OutStream'(This also adds an _Replaced to our filename) Local OutStream:TStream = WriteStream(Replace(File, Left(StripDir(File), Instr(StripDir(File), ".")), Left(StripDir(File), Instr(StripDir(File), ".")-1) + "_Replaced.")) ' Our Inline and Outline variables: Local InLine:String, OutLine:String ' Variables holding the first, last, splitting characters for our variables: Local VarBeginner:String = "(" Local VarSplitter:String = "," Local VarEnder:String = ")" ' Grab the needed data: VarBeginner = Left(Right(Left(Data, Instr(Data, "*1")), 2), 1) VarSplitter = Left(Replace(Right(Data, Len(Data) - Instr(Data, "*1") - 1), " ", ""), 1) VarEnder = Left(Replace(Right(Data, Len(Data) - Instr(Data, "*2") - 1), " ", ""), 1) ' Loop until the end of the 'InStream' Repeat If (InStream.Eof()) Then Exit ' Read each line in the file: InLine = InStream.ReadLine() ' Too annoying to explain, I don't suggest looking into this: If (Instr(InLine, Left(Data, Instr(Data, VarBeginner)))) Then Local Var1:String = Right(InLine, Len(InLine) - Instr(InLine, Left(Data, Instr(Data, VarBeginner))) + Len(Left(Data, Instr(Data, VarBeginner)))) Var1 = Left(Var1, Instr(Var1, VarSplitter) - 1) Var1 = Right(Var1, Len(Var1) - Instr(Var1, VarBeginner)) Local Var2:String = Replace(Right(InLine, Len(InLine) - Instr(InLine, Var1+VarSplitter)+Len(Var1)), " ", "") Var2 = Left(Var2, Instr(Var2, VarEnder) - 1) Var2 = Right(Var2, Len(Var2) - Instr(Var2, Var1+",") + 1) Var2 = Replace(Var2, Var1+VarSplitter, "") Local FinalData:String = Replace(Replace(NewData, "*1", Var1), "*2", Var2) OutLine = InLine OutLine = Replace(OutLine, Replace(Replace(Data, "*1", Var1), "*2", Var2), FinalData) Else OutLine = InLine EndIf ' Write the edited, or non-edited line to the 'OutStream' OutStream.WriteLine(OutLine) InLine = "" OutLine = "" Forever ' Close the in and out streams: CloseStream(InStream) CloseStream(OutStream) ' Return True: Return True End Function Function Console:Int(S:String) ' If we have it enabled, print: If (ConsoleOutput = True) Then Print(S) End Function |
Comments
| ||
Cool, so it does something similar to :perl -pi -w -e 's/ListAddLast\((.*)\,(.*)\)/$1.AddLast($2)/g' *.bmx |
Code Archives Forum