using System; using System.Linq; using System.Xml.Serialization; using System.Collections.Generic; using System.Text.RegularExpressions; using Avalonia; using BFR.Helpers; using BFR.DataModels; namespace BFR.Operations { public class Replace : Operation { public override string Name => nameof(Replace); public override string Description => "Replaces the selected part of the file name."; public static readonly AvaloniaProperty ModeProperty = AvaloniaProperty.Register(nameof(Mode), ReplaceMode.Pattern); public ReplaceMode Mode { get => GetValue(ModeProperty); set => SetValue(ModeProperty, value); } [XmlIgnore] public ReplaceOperationMode[] Modes => ReplaceOperationMode.Modes; public string Replacement { get; set; } = ""; public bool FullName { get; set; } = false; public string Pattern { get; set; } = ""; public bool UseRegex { get; set; } = false; public bool UseRegexReplace { get; set; } = false; public string Characters { get; set; } = ""; public int FirstN { get; set; } = 0; public int LastN { get; set; } = 0; public int FromN { get; set; } = 0; public int ToN { get; set; } = 0; protected override void ApplyToInternal(IList files) { // Fail conditions: Various out-of-bounds var shortestLength = files.Min(x => FullName ? x.FullName.Length : x.Name.Length); if (Mode == ReplaceMode.FirstN && FirstN > shortestLength) throw new OperationException($"First N can't be greater than the shortest file name length ({shortestLength})."); if (Mode == ReplaceMode.LastN && LastN > shortestLength) throw new OperationException($"Last N can't be greater than the shortest file name length ({shortestLength})."); if (Mode == ReplaceMode.FromNToN && FromN > shortestLength) throw new OperationException($"From N can't be greater than the shortest file name length ({shortestLength})."); if (Mode == ReplaceMode.FromNToN && ToN > shortestLength) throw new OperationException($"To N can't be greater than the shortest file name length ({shortestLength})."); if (Mode == ReplaceMode.FromNToN && FromN > ToN) throw new OperationException("From N can't be greater than To N."); // Regex Failure if(Mode == ReplaceMode.Pattern && UseRegex) try { "".Replace(Pattern, Replacement, true, false); } catch(Exception) { throw new OperationException("Invalid Regex Pattern."); } // Apply operation foreach(var file in files) { var newName = FullName ? file.FullName : file.Name; newName = Mode switch { ReplaceMode.Pattern => newName.Replace(Pattern, Replacement, UseRegex, UseRegexReplace), ReplaceMode.Characters => Characters.Length > 0 ? Regex.Replace(newName, $"[{Characters}]", Replacement.Replace("$", "$$")) : newName, ReplaceMode.FromNToN => Regex.Replace(newName, $"^(.{{{FromN}}}).+(.{{{newName.Length - ToN - 1}}})$", $"$1{Replacement.Replace("$", "$$")}$2"), ReplaceMode.FirstN => Regex.Replace(newName, $"^.{{{FirstN}}}", Replacement.Replace("$", "$$")), ReplaceMode.LastN => Regex.Replace(newName, $".{{{LastN}}}$", Replacement.Replace("$", "$$")), _ => newName }; if (FullName) file.FullName = newName; else file.Name = newName; } } } }