private void PrintFileError(FileParseError status, String relpath) { if (status == (SuppressError & status)) { return; } String full_path = Path.GetFullPath(relpath); String message = null; switch (status) { case FileParseError.FileTooLarge: message = String.Format("File '{0}' is too large for processing.", full_path); break; case FileParseError.InvalidCharacter: message = String.Format("File '{0}' contains unsupported control characters.", full_path); break; default: throw new ApplicationException("Unknown status code."); } PrintError(message); }
private void PrintFileError( FileParseError status, String relpath ) { if ( status == ( SuppressError & status ) ) { return; } String full_path = Path.GetFullPath( relpath ); String message = null; switch ( status ) { case FileParseError.FileTooLarge : message = String.Format( "File '{0}' is too large for processing.", full_path ); break; case FileParseError.InvalidCharacter : message = String.Format( "File '{0}' contains unsupported control characters.", full_path ); break; default : throw new ApplicationException( "Unknown status code." ); } PrintError( message ); }
public void VisitFile(String relpath) { FilesProcessed++; // Make a note of how we need to open files. FileAccess file_access = FileAccess.Read; FileShare file_share = FileShare.Read; if (ActiveReplace && ReplacementText != null) { file_access = FileAccess.ReadWrite; file_share = FileShare.None;; } FileStream fs = null; try { fs = new FileStream(relpath, FileMode.Open, file_access, file_share); } catch (IOException) { FilesSkipped++; PrintFileError(FileParseError.FileIOError, relpath); return; } using (fs) using (StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default, true)) { String text; FileParseError status = ReadCanonicalTextStream(sr, fs.Length, out text); if (status != FileParseError.None) { FilesSkipped++; PrintFileError(status, relpath); return; } MatchCollection matches = UserRegex.Matches(text); if (matches.Count == 0) { return; } FilesFound++; MatchesFound += matches.Count; foreach (Match m in matches) { // Count number of line-starts to our left to get a 1-based row number. int lineNum = LineStartRTL.Matches(text, m.Index).Count; // Calculate the column number (0-based). int columnNum = m.Index - LineStartRTL.Match(text, m.Index).Index; // Extend the match to include the whole line(s) of text, for display purposes. int matchBegin = m.Index; int matchEnd = m.Index + m.Length; int lineBegin = LineStartRTL.Match(text, matchBegin).Index; int lineEnd = LineTermLTR.Match(text, matchEnd).Index; // For matches on very long lines: clip begin and end at +/- 40 chars from match. int lineWidth = lineEnd - lineBegin; if (lineWidth > OutputWidth) { int lineBegin0 = lineBegin; int lineEnd0 = lineEnd; int middle = m.Index + (m.Length / 2); lineBegin = Math.Min(Math.Max(lineBegin0, middle - (OutputWidth / 2)), matchBegin); lineEnd = Math.Min(Math.Max(matchEnd, middle + (OutputWidth / 2)), lineEnd0); // But if we're up against one side or the other, extend outward in the other direction. if (lineEnd - lineBegin < OutputWidth) { lineBegin = Math.Max(lineBegin0, lineEnd - OutputWidth); lineEnd = Math.Min(lineEnd0, lineBegin + OutputWidth); } } // Populate 3 strings for output in different colors: head, match, tail string lineTextHead = text.Substring(lineBegin, matchBegin - lineBegin); string lineTextMatch = text.Substring(matchBegin, m.Length); string lineTextTail = text.Substring(matchEnd, lineEnd - matchEnd); // Replace tabs with single-spaces. lineTextHead = lineTextHead.Replace('\t', ' '); lineTextMatch = lineTextMatch.Replace('\t', ' '); lineTextTail = lineTextTail.Replace('\t', ' '); // Replace linefeeds with ¶ markers. lineTextHead = lineTextHead.Replace('\n', '¶'); lineTextMatch = lineTextMatch.Replace('\n', '¶'); lineTextTail = lineTextTail.Replace('\n', '¶'); // Print the file name and match location. FileInfo file_info = new FileInfo(Path.GetFullPath(relpath)); Win32.TrySetConsoleColor(FileDirectoryColor); Console.Write(file_info.Directory.FullName + Path.DirectorySeparatorChar); Win32.TrySetConsoleColor(FileNameColor); Console.Write(file_info.Name); Win32.TrySetConsoleColor(LineNumberColor); Console.Write("(" + lineNum + "," + columnNum + "): "); Win32.TrySetConsoleColor(DefaultColor); Console.WriteLine(); if (ReplacementText != null) { Int32 match_len = lineTextMatch.Length; lineTextMatch = UserRegex.Replace(lineTextMatch, ReplacementText); if (lineTextMatch.Length > match_len) { Int32 adjust = lineTextMatch.Length - match_len; if (adjust > 0) { if (adjust == lineTextHead.Length) { lineTextHead = String.Empty; } else if (adjust > lineTextHead.Length) { adjust -= lineTextHead.Length; lineTextHead = String.Empty; if (adjust > 0) { if (adjust >= lineTextTail.Length) { lineTextTail = String.Empty; } else { lineTextTail = lineTextTail.Substring(adjust); } } } else { lineTextHead = lineTextHead.Substring(adjust); } } } } // Print the match, in 3 syntax-highlighted parts. Win32.TrySetConsoleColor(SurroundingTextColor); Console.Write(lineTextHead); Win32.TrySetConsoleColor(MatchedTextColor); Console.Write(lineTextMatch); Win32.TrySetConsoleColor(SurroundingTextColor); Console.Write(lineTextTail); Win32.TrySetConsoleColor(DefaultColor); Console.WriteLine(); Console.WriteLine(); } if (ActiveReplace && ReplacementText != null) { if (BackupDirectory != null) { string backup_file = Path.Combine(BackupDirectory, new FileInfo(Path.GetFullPath(relpath)).Name + ".bak"); if (File.Exists(backup_file)) { File.Delete(backup_file); } // let the exception fall out if the path is invalid, better to fail the // replacement than to silently ignore the backup! using (FileStream backup_stream = File.Create(backup_file)) using (StreamWriter backup_writer = new StreamWriter(backup_stream, sr.CurrentEncoding)) { backup_writer.Write(text); backup_writer.Flush(); } } // Reset the stream-length and file-pointer -- write the modified text, taking care to preserve // the original encoding. fs.SetLength(0); using (StreamWriter sw = new StreamWriter(fs, sr.CurrentEncoding)) { text = UserRegex.Replace(text, ReplacementText); foreach (Char c in text) { if (c == '\n') { sw.Write(Environment.NewLine); } else { sw.Write(c); } } sw.Flush(); } } } }
// // Initialization public Settings() { // Load defaults from app.config. //todo: drive this via reflection? string val; val = ConfigurationSettings.AppSettings["OutputWidth"]; if (val == null || val == String.Empty) OutputWidth = 78; else OutputWidth = UInt16.Parse(val); val = ConfigurationSettings.AppSettings["RegexIgnoreCase"]; if (val == null || val == String.Empty) RegexIgnoreCase = false; else RegexIgnoreCase = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["RegexSingleline"]; if (val == null || val == String.Empty) RegexSingleline = false; else RegexSingleline = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["RegexMimicVS"]; if (val == null || val == String.Empty) RegexMimicVS = false; else RegexMimicVS = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["DontRecurse"]; if (val == null || val == String.Empty) DontRecurse = false; else DontRecurse = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["ActiveReplace"]; if (val == null || val == String.Empty) ActiveReplace = false; else ActiveReplace = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["BackupDirectory"]; if (val == null || val == String.Empty) BackupDirectory = null; else BackupDirectory = val; val = ConfigurationSettings.AppSettings["IgnoreHiddenDirectories"]; if (val == null || val == String.Empty) IgnoreHiddenDirectories = true; else IgnoreHiddenDirectories = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["IgnoreHiddenFiles"]; if (val == null || val == String.Empty) IgnoreHiddenFiles = true; else IgnoreHiddenFiles = Boolean.Parse(val); val = ConfigurationSettings.AppSettings["DirectoryExclusions"]; if (val == null || val == String.Empty) DirectoryExclusions = new String[0]; else DirectoryExclusions = val.Split( ';' ); val = ConfigurationSettings.AppSettings["FileExclusions"]; if (val == null || val == String.Empty) FileExclusions = new String[0]; else FileExclusions = val.Split( ';' ); val = ConfigurationSettings.AppSettings["SuppressError"]; if (val == null || val == String.Empty) SuppressError = FileParseError.None; else SuppressError = (FileParseError)Enum.Parse( typeof( FileParseError ), val ); // The following parameters have no defaults -- they can/must only be // specified explicitly in the UI. BaseDirectory = null; FilePattern = null; RegexPattern = null; ReplacementText = null; val = ConfigurationSettings.AppSettings["ConsoleColor"]; if ( val == null || val == String.Empty ) val = "Black, White, BrightGreen, BrightGreen, BrightWhite, Gray, BrightGreen, BrightRed"; String[] color = val.Split( ',' ); for ( int i = 0; i < 8; i++ ) { color[i] = color[i].Trim(); } Win32.ConsoleColorFlags background = (Win32.ConsoleColorFlags)Enum.Parse( typeof( Win32.ConsoleColorFlags ), "Background" + color[ 0 ], true ); this.DefaultColor = ParseForeColor( color[ 1 ], background ); this.FileDirectoryColor = ParseForeColor( color[ 2 ], background ); this.FileNameColor = ParseForeColor( color[ 3 ], background ); this.LineNumberColor = ParseForeColor( color[ 4 ], background ); this.SurroundingTextColor = ParseForeColor( color[ 5 ], background ); this.MatchedTextColor = ParseForeColor( color[ 6 ], background ); this.ErrorColor = ParseForeColor( color[ 7 ], background ); }