Skip to content

Commit 02b4d3c

Browse files
committed
Add search and replace command to GMDTool
1 parent 87ec659 commit 02b4d3c

File tree

3 files changed

+188
-21
lines changed

3 files changed

+188
-21
lines changed

src/GMDTool/GMDTool.csproj

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<OutputType>Exe</OutputType>
5-
<TargetFramework>net5.0</TargetFramework>
6-
</PropertyGroup>
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net5.0</TargetFramework>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
78

8-
<ItemGroup>
9-
<PackageReference Include="CommandLineParser" Version="2.3.0" />
10-
</ItemGroup>
9+
<ItemGroup>
10+
<PackageReference Include="Colorful.Console" Version="1.2.15" />
11+
<PackageReference Include="CommandLineParser" Version="2.3.0" />
12+
</ItemGroup>
1113

12-
<ItemGroup>
13-
<ProjectReference Include="..\Cirilla.Core\Cirilla.Core.csproj" />
14-
</ItemGroup>
14+
<ItemGroup>
15+
<ProjectReference Include="..\Cirilla.Core\Cirilla.Core.csproj" />
16+
</ItemGroup>
1517

1618
</Project>

src/GMDTool/Options.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CommandLine;
2+
using System.Collections.Generic;
23

34
namespace GMDTool
45
{
@@ -14,4 +15,33 @@ class PrintOptions
1415
[Option("json", HelpText = "Output JSON")]
1516
public bool OutputJson { get; set; }
1617
}
18+
19+
[Verb("search")]
20+
class SearchOptions
21+
{
22+
[Option('i', "in", Required = true, HelpText = "Folder containing source files")]
23+
public string Input { get; set; }
24+
25+
[Option('s', "search", Required = true, HelpText = "What string to search for")]
26+
public IEnumerable<string> Search { get; set; }
27+
}
28+
29+
[Verb("replace")]
30+
class ReplaceOptions
31+
{
32+
[Option('i', "in", Required = true, HelpText = "Folder containing source files")]
33+
public string Input { get; set; }
34+
35+
[Option('o', "output", Required = true, HelpText = "Where to place the patches files")]
36+
public string Output { get; set; }
37+
38+
[Option('s', "search", Required = true, HelpText = "What string to search for")]
39+
public string Search { get; set; }
40+
41+
[Option('r', "replace", Required = true, HelpText = "Replace found string with this string")]
42+
public string ReplaceWith { get; set; }
43+
44+
[Option('p', "preview", HelpText = "Preview changes, but don't apply them")]
45+
public bool Preview { get; set; }
46+
}
1747
}

src/GMDTool/Program.cs

Lines changed: 146 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,51 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
4+
using System.Drawing;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Text.RegularExpressions;
8+
using System.Threading;
39
using Cirilla.Core.Models;
410
using CommandLine;
511

612
namespace GMDTool
713
{
814
class Program
915
{
16+
public record UpdatedEntry(string Key, string OldValue, string NewValue);
17+
1018
static int Main(string[] args)
1119
{
12-
int res = Parser.Default.ParseArguments<PrintOptions>(args)
20+
int res = Parser.Default.ParseArguments<PrintOptions, SearchOptions, ReplaceOptions>(args)
1321
.MapResult(
14-
(PrintOptions opts) => RunPrintAndReturnExitCode(opts),
15-
errs => 1);
22+
(PrintOptions opts) => Print(opts),
23+
(SearchOptions opts) => Search(opts),
24+
(ReplaceOptions opts) => Replace(opts),
25+
errs => 1);
1626

1727
if (Debugger.IsAttached)
28+
{
29+
Console.WriteLine("Debugger detected. Press enter to exit...");
1830
Console.ReadLine();
31+
}
1932

2033
return res;
2134
}
2235

23-
private static int RunPrintAndReturnExitCode(PrintOptions opts)
36+
private static void PrintEntry(IGMD_Entry entry)
37+
{
38+
string key = "(NO_KEY)";
39+
40+
if (entry as GMD_Entry is var x && x != null)
41+
key = x.Key;
42+
43+
Colorful.Console.Write(key, Color.Cyan);
44+
Colorful.Console.Write(":");
45+
Colorful.Console.WriteLine(entry.Value, Color.Orange);
46+
}
47+
48+
private static int Print(PrintOptions opts)
2449
{
2550
GMD gmd;
2651

@@ -38,17 +63,127 @@ private static int RunPrintAndReturnExitCode(PrintOptions opts)
3863

3964
foreach (var entry in gmd.Entries)
4065
{
41-
string key = "\"\"";
42-
string value = '"' + entry.Value + '"';
66+
PrintEntry(entry);
67+
}
68+
69+
return 0;
70+
}
71+
72+
private static int Search(SearchOptions opts)
73+
{
74+
string[] files = Directory.GetFiles(opts.Input, "*.gmd", SearchOption.AllDirectories);
75+
76+
foreach (var file in files)
77+
{
78+
var matches = new List<IGMD_Entry>();
79+
80+
try
81+
{
82+
var gmd = new GMD(file);
83+
84+
foreach (var entry in gmd.Entries)
85+
{
86+
if (opts.Search.Any(x => Regex.IsMatch(entry.Value, x)))
87+
matches.Add(entry);
88+
}
89+
90+
if (matches.Count > 0)
91+
{
92+
Colorful.Console.WriteLine(file, Color.Green);
93+
foreach (var entry in matches)
94+
PrintEntry(entry);
95+
Console.WriteLine();
96+
}
97+
}
98+
catch (Exception ex)
99+
{
100+
Console.WriteLine("Error: " + ex);
101+
}
102+
}
103+
104+
return 0;
105+
}
106+
107+
private static int Replace(ReplaceOptions opts)
108+
{
109+
110+
string[] files = Directory.GetFiles(opts.Input, "*.gmd", SearchOption.AllDirectories);
111+
112+
int itemCount = files.Length;
113+
int processedCount = 0;
114+
int changedFilesCount = 0;
115+
int changedValuesCount = 0;
116+
var sw = Stopwatch.StartNew();
117+
118+
Console.WriteLine("Total files: " + itemCount);
119+
Console.WriteLine("Preview mode: " + opts.Preview);
120+
121+
foreach (var file in files)
122+
{
123+
try
124+
{
125+
var changes = new List<UpdatedEntry>();
126+
var gmd = new GMD(file);
127+
128+
foreach (var entry in gmd.Entries)
129+
{
130+
string val = Regex.Replace(entry.Value, opts.Search, opts.ReplaceWith);
131+
if (entry.Value != val)
132+
{
133+
string key = "(NO_KEY)";
134+
135+
if (entry as GMD_Entry is var x && x != null)
136+
key = x.Key;
137+
138+
changes.Add(new UpdatedEntry(key, entry.Value, val));
139+
entry.Value = val;
140+
}
141+
}
142+
143+
if (changes.Count > 0)
144+
{
145+
string relPath = Path.GetRelativePath(opts.Input, file);
146+
string dest = Path.Join(opts.Output, relPath);
43147

44-
if (entry as GMD_Entry is var x && x != null)
45-
key = '"' + x.Key + '"';
46-
else if (opts.IncludeAll == false)
47-
continue; // If entry has no key and IncludeAll is false then don't print it
148+
Colorful.Console.Write(file, Color.Red);
149+
Console.Write(" -> ");
150+
Colorful.Console.WriteLine(dest, Color.LightGreen);
151+
Colorful.Console.WriteLine("Changes: " + changes.Count, Color.Yellow);
48152

49-
Console.WriteLine(key + " = " + value);
153+
foreach (var change in changes)
154+
{
155+
Colorful.Console.WriteLine(change.Key, Color.Cyan);
156+
Colorful.Console.Write(change.OldValue, Color.Orange);
157+
Console.Write(" -> ");
158+
Colorful.Console.WriteLine(change.NewValue, Color.Green);
159+
Console.WriteLine();
160+
}
161+
162+
if (!opts.Preview)
163+
{
164+
string? dir = Path.GetDirectoryName(dest);
165+
if (dir != null) Directory.CreateDirectory(dir);
166+
gmd.Save(dest);
167+
}
168+
}
169+
}
170+
catch (Exception ex)
171+
{
172+
Console.WriteLine($"Error {ex} in '{file}'");
173+
}
174+
175+
Interlocked.Increment(ref processedCount);
50176
}
51177

178+
sw.Stop();
179+
180+
Console.WriteLine();
181+
Console.WriteLine("Finished!");
182+
Console.WriteLine("Processed: " + processedCount);
183+
Console.WriteLine("Changed files: " + changedFilesCount);
184+
Console.WriteLine("Changed values: " + changedValuesCount);
185+
Console.WriteLine("Elapsed: " + sw.Elapsed);
186+
52187
return 0;
53188
}
54189
}

0 commit comments

Comments
 (0)