Beispiel #1
0
        public static void RegisterMatchRegex(CmdlineParser parser)
        {
            var cmdRegex = parser.AddCommand("match-regex", "match regex groups", (parserRegex) =>
            {
                var _regex = parserRegex.AddMandatoryParameter("regex", "c# regex");
                var _fmt   = parserRegex.AddMandatoryParameter("fmt", "format string ( use \\N to print Nth group in place )");

                parserRegex.OnCmdlineMatch(() =>
                {
                    var regexStr = (string)_regex;
                    var fmt      = Regex.Unescape((string)_fmt);
                    using (var sr = new StreamReader(Console.OpenStandardInput()))
                    {
                        var s   = sr.ReadToEnd();
                        var rgx = new Regex(regexStr /*, RegexOptions.Singleline*/).Match(s);
                        if (rgx.Success)
                        {
                            for (int i = 1; i < rgx.Groups.Count; ++i)
                            {
                                fmt = fmt.Replace($"\\{i}", rgx.Groups[i].Value);
                            }
                            System.Console.WriteLine(fmt);
                            Environment.Exit(0);
                        }
                        Environment.Exit(1);
                    }
                });
            });
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            CmdlineParser.Create("sample application", (parser) =>
            {
                var cmdConfig = parser.AddCommand("config", "configuration", (pConfig) =>
                {
                    var cmdConfigShow   = pConfig.AddCommand("show", "show current config");
                    var cmdConfigUpdate = pConfig.AddCommand("update", "update config item", (pConfigUpdate) =>
                    {
                        var param = pConfigUpdate.AddMandatoryParameter("var=value", "assign value to var");
                        pConfigUpdate.OnCmdlineMatch(() =>
                        {
                            System.Console.WriteLine($"setting [{(string)param}]");
                        });
                    });

                    pConfig.OnCmdlineMatch(() =>
                    {
                        if (cmdConfigShow)
                        {
                            System.Console.WriteLine($"showing configuration...");
                        }
                    });
                });

                parser.AddShort("h", "show usage", null, (item) => item.MatchParser.PrintUsage());

                parser.OnCmdlineMatch(() =>
                {
                });

                parser.Run(args);
            });
        }
Beispiel #3
0
        public static void RegisterLogic2FreqGraph(CmdlineParser parser)
        {
            var cmdReplaceToken = parser.AddCommand("logic2-freq-graph", "display pulse freq graph", (logic2FreqGraph) =>
            {
                var _filename      = logic2FreqGraph.AddMandatoryParameter("filename", "Logic2 exported csv file");
                var _columnsFilter = logic2FreqGraph.AddMandatoryParameter("columnsFilter", "filter for csv columns (eg. \"Channel 0, Channel 2\")");

                logic2FreqGraph.OnCmdlineMatch(() =>
                {
                    var pathfilename = (string)_filename;
                    if (!File.Exists(pathfilename))
                    {
                        System.Console.WriteLine($"can't find file [{pathfilename}]");
                        return;
                    }

                    var columnsFilter = (string)_columnsFilter;

                    MainWindow.csv_pathfilename = pathfilename;
                    MainWindow.chansFilter      = columnsFilter;

                    GuiToolkit.CreateGui <MainWindow>();
                });
            });
        }
Beispiel #4
0
        public static void RegisterReplaceToken(CmdlineParser parser)
        {
            var cmdReplaceToken = parser.AddCommand("replace-token", "replace token from given standard input (not optimized for huge files)", (parserReplaceToken) =>
            {
                var flagCSharpRegex = parserReplaceToken.AddShort("csregex", "token will treated as csharp regex");
                var _token          = parserReplaceToken.AddMandatoryParameter("token", "token to search for");
                var _replacement    = parserReplaceToken.AddMandatoryParameter("replacement", "text to replace where token was found");

                parserReplaceToken.OnCmdlineMatch(() =>
                {
                    var token       = (string)_token;
                    var replacement = Regex.Unescape((string)_replacement);
                    using (var sr = new StreamReader(Console.OpenStandardInput()))
                    {
                        var s = sr.ReadToEnd();
                        if (flagCSharpRegex)
                        {
                            var rgx = new Regex(token, RegexOptions.Singleline);
                            System.Console.Write(rgx.Replace(s, replacement));
                        }
                        else
                        {
                            System.Console.Write(s.Replace(token, replacement));
                        }
                    }
                });
            });
        }
Beispiel #5
0
        public static void RegisterAutoCPULimiter(CmdlineParser parser)
        {
            var DEFAULT_mincpu_find = 50d;
            var DEFAULT_maxcpu_set  = 20d;

            var cmdRegex = parser.AddCommand("cpu-autolimiter", "autolimit cpu usage for processes that uses more than mincpu-find", (parserCpuLimiter) =>
            {
                var _mincpu_find = parserCpuLimiter.AddShort("mincpu-find",
                                                             Invariant($"minimum cpu load to match process [default={DEFAULT_mincpu_find}]"), "val");

                var _maxcpu_set = parserCpuLimiter.AddShort("maxcpu-set",
                                                            Invariant($"maximum cpu load to set on matched processes [default={DEFAULT_maxcpu_set}]"), "val");

                parserCpuLimiter.OnCmdlineMatch(() =>
                {
                    var mincpu_find = _mincpu_find.ArgValues.Count == 0 ? DEFAULT_mincpu_find : ((string)_mincpu_find).InvDoubleParse();
                    var maxcpu_set  = _maxcpu_set.ArgValues.Count == 0 ? DEFAULT_maxcpu_set : ((string)_maxcpu_set).InvDoubleParse();

                    if (UtilToolkit.SearchInPath("cpustat") == null)
                    {
                        System.Console.WriteLine($"requirements: apt install cpustat");
                        return;
                    }

                    if (UtilToolkit.SearchInPath("cpulimit") == null)
                    {
                        System.Console.WriteLine($"requirements: apt install cpulimit");
                        return;
                    }

                    var task = Exec("cpustat", new[] { "1", "1" }, CancellationToken.None, false);
                    task.Wait();
                    var pid_cpu_lines = task.Result.Output.Lines().Skip(1)
                                        .Select(line =>
                    {
                        var ss      = line.Split(" ").Select(w => w.Trim()).Where(r => r.Length > 0).ToArray();
                        var pid     = ss[3];
                        var cpu     = ss[0].InvDoubleParse();
                        var cmdline = ss[7];

                        return(new
                        {
                            pid = pid,
                            cpu = cpu,
                            cmdline = cmdline
                        });
                    })
                                        .Where(r => r.cpu >= mincpu_find)
                                        .ToList();

                    foreach (var x in pid_cpu_lines)
                    {
                        Console.WriteLine($"process pid={x.pid} with cpu={x.cpu}% will limited to cpu={maxcpu_set}% [{x.cmdline}]");

                        Exec("cpulimit", new[] { "--background", "--pid", $"{x.pid}", "--limit", $"{maxcpu_set}" }, CancellationToken.None);
                    }
                });
            });
        }
Beispiel #6
0
        static void Main(string[] args)
        {
            CmdlineParser.Create("shell utils", (parser) =>
            {
                parser.AddShortLong("h", "help", "show usage", null, (item) => item.MatchParser.PrintUsage());

                ShellUtilities.RegisterReplaceToken(parser);
                ShellUtilities.RegisterMatchRegex(parser);
                ShellUtilities.RegisterAutoCPULimiter(parser);
                ShellUtilities.RegisterGraphArea(parser);
                ShellUtilities.RegisterLogic2FreqGraph(parser);

                parser.OnCmdlineMatch(() =>
                {
                });

                parser.Run(args);
            }, useColors: true, unescapeArguments: true);
        }
Beispiel #7
0
        static void Main(string[] args)
        {
            var cmd        = new CmdlineParser();
            var parameters = cmd.Parse(args);

            if (parameters != null)
            {
                // consume Options instance properties
                if (!parameters.ContainsKey("tool"))
                {
                    Console.WriteLine("No tool specified");
                }
                else
                {
                    var opennlpCore = new OpenNlpCore(parameters);
                    opennlpCore.Process();
                }
            }
        }
Beispiel #8
0
        public void Run(string[] args)
        {
            var cts = new CancellationTokenSource();

            ct = cts.Token;

            Console.CancelKeyPress += (s, e) =>
            {
                e.Cancel = true;
                cts.Cancel();
            };

            CmdlineParser.Create("Synchronize btrfs SOURCE filesystem with given TARGET.", (parser) =>
            {
                parser.AddShortLong("h", "help", "show usage", null, (item) => item.MatchParser.PrintUsage());

                var dryRunMode       = parser.AddShortLong("u", "dry-run", "list sync actions without apply (simulation mode)");
                var skipSnapResync   = parser.AddShortLong("n", "skip-snap-resync", "avoid resync existing subvolume snapshots");
                var skipDeleteSubvol = parser.AddShortLong("s", "skip-del-subvol", "avoid to remove destination subvol not present in source");

                var SourcePath = parser.AddMandatoryParameter("source", "source path");
                var TargetPath = parser.AddMandatoryParameter("target", "target path");

                parser.OnCmdlineMatch(() =>
                {
                    Task.Run(async() =>
                    {
                        var runMode = RunMode.normal;
                        if (dryRunMode)
                        {
                            runMode = RunMode.dryRun;
                        }

                        await RunIt(runMode, SourcePath, TargetPath, skipSnapResync, skipDeleteSubvol);
                    }).Wait();
                });

                parser.Run(args);
            });
        }
Beispiel #9
0
        static void Main(string[] args)
        {
            CmdlineParser.Create("clone disk reading parallel to write", (parser) =>
            {
                var nonInteractive = parser.AddLong("non-interactive", "doesn't prompt before to start");
                var sourceDevParam = parser.AddMandatoryParameter("source", "source device");
                var targetDevParam = parser.AddMandatoryParameter("target", "target device");

                parser.OnCmdlineMatch(() =>
                {
                    var sourceDevice = (string)sourceDevParam;
                    var destDevice   = (string)targetDevParam;

                    if (!nonInteractive)
                    {
                        System.Console.WriteLine($"all content of device [{destDevice}] will overwritted");
                        System.Console.WriteLine($"press ctrl+c to abort");
                        Console.ReadKey();
                    }

                    int bucketCount    = 8;
                    int bucketSize     = 512 * 2 * 1024 * 64; // 64MB
                    byte[][] buckets   = new byte[bucketCount][];
                    int[] bucketLength = new int[bucketCount];
                    for (int i = 0; i < bucketCount; ++i)
                    {
                        buckets[i] = new byte[bucketSize];
                    }

                    int readerNextBucket          = 0;
                    int readerNextWriteWaitHandle = 0;
                    long readOffset = 0L;
                    WaitHandle[] readWaitHandles = new WaitHandle[bucketCount];
                    for (int i = 0; i < bucketCount; ++i)
                    {
                        readWaitHandles[i] = new AutoResetEvent(true);
                    }

                    int writerNextBucket          = 0;
                    int writerNextReadWaitHandle  = 0;
                    long writeOffset              = 0L;
                    WaitHandle[] writeWaitHandles = new WaitHandle[bucketCount];
                    for (int i = 0; i < bucketCount; ++i)
                    {
                        writeWaitHandles[i] = new AutoResetEvent(false);
                    }

                    var sourceSize = GetDeviceSize(sourceDevice);
                    var destSize   = GetDeviceSize(destDevice);

                    Console.WriteLine($"source disk = {sourceDevice} size = {sourceSize.HumanReadable()}");
                    Console.WriteLine($"  dest disk = {destDevice}");

                    if (destSize < sourceSize)
                    {
                        Console.WriteLine($"can't fit source into dest device");
                        Environment.Exit(3);
                    }

                    var topCursor = 0;
                    Console.Clear();

                    var fsRead = File.OpenRead(sourceDevice);
                    fsRead.Seek(0, SeekOrigin.Begin);

                    var fsWrite = File.OpenWrite(destDevice);
                    fsWrite.Seek(0, SeekOrigin.Begin);

                    object guiLock = new object();

                    var taskReader = Task.Run(() =>
                    {
                        DateTime dtReadStart = DateTime.Now;

                        while (readOffset < sourceSize)
                        {
                            readWaitHandles[readerNextBucket].WaitOne(); // initially already signaled

                            var len = fsRead.Read(buckets[readerNextBucket], 0, bucketSize);
                            bucketLength[readerNextBucket] = len;

                            long speed = (long)((double)(readOffset + len) / (DateTime.Now - dtReadStart).TotalSeconds);

                            lock (guiLock)
                            {
                                Console.SetCursorPosition(0, topCursor);
                                Console.Write($"<===  read {len} bytes to bucket N. {readerNextBucket}");
                                Console.Write($"  read offset [{readOffset.HumanReadable()}] speed = {speed.HumanReadable()}/s");
                            }

                            var writeEvt = (AutoResetEvent)writeWaitHandles[readerNextWriteWaitHandle];
                            readerNextWriteWaitHandle++;
                            writeEvt.Set();
                            if (readerNextWriteWaitHandle == bucketCount)
                            {
                                readerNextWriteWaitHandle = 0;
                            }

                            readOffset += len;
                            readerNextBucket++;
                            if (readerNextBucket == bucketCount)
                            {
                                readerNextBucket = 0;
                            }
                        }
                    });

                    var taskWriter = Task.Run(() =>
                    {
                        DateTime dtWriteStart = DateTime.Now;

                        while (writeOffset < sourceSize)
                        {
                            writeWaitHandles[writerNextBucket].WaitOne();

                            var len = bucketLength[writerNextBucket];

                            fsWrite.Write(buckets[writerNextBucket], 0, len);

                            long speed = (long)((double)(writeOffset + len) / (DateTime.Now - dtWriteStart).TotalSeconds);

                            lock (guiLock)
                            {
                                Console.SetCursorPosition(0, topCursor + 1);
                                Console.Write($"===> write {len} bytes to bucket N. {writerNextBucket}");
                                Console.Write($" write offset [{writeOffset.HumanReadable()}] speed = {speed.HumanReadable()}/s");
                            }

                            var readEvt = (AutoResetEvent)readWaitHandles[writerNextReadWaitHandle];
                            writerNextReadWaitHandle++;
                            readEvt.Set();
                            if (writerNextReadWaitHandle == bucketCount)
                            {
                                writerNextReadWaitHandle = 0;
                            }

                            writeOffset += len;
                            writerNextBucket++;
                            if (writerNextBucket == bucketCount)
                            {
                                writerNextBucket = 0;
                            }
                        }
                    });

                    Task.WaitAll(new Task[] { taskReader, taskWriter });

                    Console.SetCursorPosition(0, topCursor + 2);
                    Console.WriteLine("*** FINISHED ***");
                });

                parser.Run(args);
            });
        }
Beispiel #10
0
        public static void RegisterGraphArea(CmdlineParser parser)
        {
            var cmdReplaceToken = parser.AddCommand("graph-area", "compute area under graph XY", (parserGraphArea) =>
            {
                var _decimalDelimiter = parserGraphArea.AddShort("d", "decimal separator (default=.)", "VAL");
                var _fieldDelimiter   = parserGraphArea.AddShort("f", "field separator (default=,)", "VAL");
                var _genDxf           = parserGraphArea.AddShort("x", "generate dxf lwpolyline output");
                var _filename         = parserGraphArea.AddMandatoryParameter("filename", "simple XY column file");

                parserGraphArea.OnCmdlineMatch(() =>
                {
                    var genDxf = (bool)_genDxf;

                    var pathfilename = (string)_filename;
                    if (!File.Exists(pathfilename))
                    {
                        System.Console.WriteLine($"can't find file [{pathfilename}]");
                        return;
                    }

                    string dxfPathfilename = null;
                    netDxf.DxfDocument dxf = null;
                    if (genDxf)
                    {
                        dxfPathfilename = Path.Combine(
                            Path.GetDirectoryName(pathfilename), Path.GetFileNameWithoutExtension(pathfilename) + ".dxf");
                        dxf = new netDxf.DxfDocument();
                    }

                    var decDelim   = (string)_decimalDelimiter;
                    var fieldDelim = (string)_fieldDelimiter;

                    if (decDelim == null)
                    {
                        decDelim = ".";
                    }
                    if (fieldDelim == null)
                    {
                        fieldDelim = ",";
                    }

                    var ni = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
                    ni.NumberDecimalSeparator = decDelim;

                    var area = 0d;

                    var pts = new List <XYPt>();

                    using (var sr = new StreamReader(pathfilename))
                    {
                        while (!sr.EndOfStream)
                        {
                            var line = sr.ReadLine().Trim();
                            if (line.Length != 0)
                            {
                                var ss = line.Split(fieldDelim);
                                var x  = double.Parse(ss[0], ni);
                                var y  = double.Parse(ss[1], ni);
                                pts.Add(new XYPt()
                                {
                                    x = x, y = y
                                });
                            }
                        }
                    }

                    pts = pts.OrderBy(w => w.x).ToList();

                    var MINY = pts.Min(w => w.y);

                    var prevx = 0d;
                    var prevy = 0d;
                    int cnt   = 0;

                    netDxf.Entities.LwPolyline lw = null;
                    if (dxf != null)
                    {
                        lw = new netDxf.Entities.LwPolyline();
                    }

                    foreach (var pt in pts)
                    {
                        if (dxf != null)
                        {
                            lw.Vertexes.Add(new netDxf.Entities.LwPolylineVertex(pt.x, pt.y));
                        }
                        if (cnt > 0)
                        {
                            var maxy = Max(prevy, pt.y);
                            var miny = Min(prevy, pt.y);
                            var b    = (pt.x - prevx);
                            area    += b * (miny - MINY) + b * (maxy - miny) / 2;
                        }

                        prevx = pt.x;
                        prevy = pt.y;

                        ++cnt;
                    }

                    System.Console.WriteLine(Invariant($"area: {area}"));

                    if (dxf != null)
                    {
                        dxf.AddEntity(lw);
                        dxf.Save(dxfPathfilename, true);
                        System.Console.WriteLine($"[{dxfPathfilename}] written.");
                    }
                });
            });
        }
Beispiel #11
0
        static void Main(string[] args)
        {
            CmdlineParser.Create("Shows only difference between files", (p) =>
            {
                var showStats = p.AddShortLong("s", "all-stats", "shows all stats informations");
                var showDiff  = p.AddShortLong("d", "show-differences", "shows characters difference");

                var file1 = p.AddMandatoryParameter("file1", "first file");
                var file2 = p.AddMandatoryParameter("file2", "second file");

                p.OnCmdlineMatch(() =>
                {
                    var charDiffers1   = 0;
                    var charDiffers2   = 0;
                    var maxChangeWidth = 0;
                    var lineDiffers1   = 0;
                    var lineDiffers2   = 0;
                    var totalLines1    = 0;
                    var totalLines2    = 0;
                    var filesize1      = new FileInfo(file1).Length;
                    var filesize2      = new FileInfo(file2).Length;

                    #region detect maxChangeWidth
                    {
                        using (var sr1 = new StreamReader(file1))
                        {
                            using (var sr2 = new StreamReader(file2))
                            {
                                // detect max change width

                                while (!sr1.EndOfStream && !sr2.EndOfStream)
                                {
                                    var changed = 0;

                                    var line1 = sr1.ReadLine();
                                    var line2 = sr2.ReadLine();

                                    ++totalLines1;
                                    ++totalLines2;

                                    var len1   = line1.Length;
                                    var len2   = line2.Length;
                                    var lenmax = Max(len1, len2);

                                    int i1 = 0;
                                    int i2 = 0;

                                    while (true)
                                    {
                                        if (len1 == 0)
                                        {
                                            var r         = len2 - i2 - 1;
                                            changed      += r;
                                            charDiffers2 += r;
                                            break;
                                        }
                                        else if (len2 == 0)
                                        {
                                            var r         = len1 - i1 - 1;
                                            changed      += r;
                                            charDiffers1 += r;
                                            break;
                                        }
                                        if (line1[i1] != line2[i2])
                                        {
                                            ++changed;

                                            if (i1 < len1 - 1 && line1[i1 + 1] == line2[i2])
                                            {
                                                ++charDiffers1;
                                                ++i1;
                                            }
                                            else if (i2 < len2 - 1 && line2[i2 + 1] == line1[i1])
                                            {
                                                ++i2;
                                                ++charDiffers2;
                                            }
                                            else
                                            {
                                                ++i1;
                                                ++i2;
                                                ++charDiffers1;
                                                ++charDiffers2;
                                            }
                                        }
                                        else
                                        {
                                            ++i1;
                                            ++i2;
                                        }
                                        if (i1 >= len1 && i2 >= len2)
                                        {
                                            break;
                                        }
                                        else if (i1 >= len1)
                                        {
                                            var r         = len2 - i2 - 1;
                                            changed      += r;
                                            charDiffers2 += r;
                                            break;
                                        }
                                        else if (i2 >= len2)
                                        {
                                            var r         = len1 - i1 - 1;
                                            changed      += r;
                                            charDiffers1 += r;
                                            break;
                                        }
                                    }

                                    if (changed > 0)
                                    {
                                        ++lineDiffers1;
                                        ++lineDiffers2;
                                    }

                                    maxChangeWidth = Max(maxChangeWidth, changed);
                                }

                                if (!sr1.EndOfStream)
                                {
                                    while (!sr1.EndOfStream)
                                    {
                                        var line1 = sr1.ReadLine();

                                        ++totalLines1;
                                        ++lineDiffers1;

                                        var len1 = line1.Length;

                                        maxChangeWidth = Max(maxChangeWidth, len1);
                                        charDiffers1  += len1;
                                    }
                                }

                                if (!sr2.EndOfStream)
                                {
                                    while (!sr2.EndOfStream)
                                    {
                                        var line2 = sr2.ReadLine();

                                        ++totalLines2;
                                        ++lineDiffers2;

                                        var len2 = line2.Length;

                                        maxChangeWidth = Max(maxChangeWidth, len2);
                                        charDiffers2  += len2;
                                    }
                                }

                                var tblOut = new List <List <string> >();

                                if (showStats)
                                {
                                    tblOut.Add(new List <string>()
                                    {
                                        "max changed chars per line", maxChangeWidth.ToString(), maxChangeWidth.ToString()
                                    });

                                    tblOut.Add(new List <string>()
                                    {
                                        "size", filesize1.ToString(), filesize2.ToString()
                                    });

                                    tblOut.Add(new List <string>()
                                    {
                                        "lines", totalLines1.ToString(), totalLines2.ToString()
                                    });

                                    tblOut.Add(new List <string>()
                                    {
                                        "line differs", lineDiffers1.ToString(), lineDiffers2.ToString()
                                    });

                                    tblOut.Add(new List <string>()
                                    {
                                        "line differs (%)",
                                        string.Format("{0:0.0}", (double)lineDiffers1 / totalLines1 * 100),
                                        string.Format("{0:0.0}", (double)lineDiffers2 / totalLines2 * 100)
                                    });

                                    tblOut.Add(new List <string>()
                                    {
                                        "char differs", charDiffers1.ToString(), charDiffers2.ToString()
                                    });

                                    tblOut.Add(new List <string>()
                                    {
                                        "char differs (%)",
                                        string.Format("{0:0.0}", (double)charDiffers1 / filesize1 * 100),
                                        string.Format("{0:0.0}", (double)charDiffers2 / filesize2 * 100)
                                    });
                                }

                                if (tblOut.Count > 0)
                                {
                                    System.Console.WriteLine(tblOut.TableFormat(
                                                                 new[]
                                    {
                                        "",
                                        "file1",
                                        "file2"
                                    },
                                                                 new[]
                                    {
                                        ColumnAlignment.left,
                                        ColumnAlignment.right,
                                        ColumnAlignment.right
                                    }));
                                }
                            }
                        }
                    }
                    #endregion

                    #region show char changes
                    if (showDiff || p.Items.Count(w => w.Type == CmdlineParseItemType.flag && w.Matches) == 0)
                    {
                        using (var sr1 = new StreamReader(file1))
                        {
                            using (var sr2 = new StreamReader(file2))
                            {
                                var W         = Max(maxChangeWidth, "fileX".Length);
                                var firstLine = true;

                                while (!sr1.EndOfStream && !sr2.EndOfStream)
                                {
                                    var line1 = sr1.ReadLine();
                                    var line2 = sr2.ReadLine();

                                    var len1   = line1.Length;
                                    var len2   = line2.Length;
                                    var lenmax = Max(len1, len2);

                                    var sb1 = new StringBuilder();
                                    var sb2 = new StringBuilder();

                                    int i1 = 0;
                                    int i2 = 0;

                                    while (true)
                                    {
                                        if (len1 == 0)
                                        {
                                            sb2.Append(line2.Substring(i2));
                                            break;
                                        }
                                        else if (len2 == 0)
                                        {
                                            sb1.Append(line1.Substring(i1));
                                            break;
                                        }

                                        if (line1[i1] != line2[i2])
                                        {
                                            if (i1 < len1 - 1 && line1[i1 + 1] == line2[i2])
                                            {
                                                sb1.Append(line1[i1]);
                                                ++i1;
                                            }
                                            else if (i2 < len2 - 1 && line2[i2 + 1] == line1[i1])
                                            {
                                                sb1.Append(line2[i2]);
                                                ++i2;
                                            }
                                            else
                                            {
                                                ++i1;
                                                ++i2;
                                            }
                                        }
                                        else
                                        {
                                            ++i1;
                                            ++i2;
                                        }
                                        if (i1 >= len1 && i2 >= len2)
                                        {
                                            break;
                                        }
                                        else if (i1 >= len1)
                                        {
                                            sb2.Append(line2.Substring(i2));
                                            break;
                                        }
                                        else if (i2 >= len2)
                                        {
                                            sb1.Append(line1.Substring(i1));
                                            break;
                                        }
                                    }

                                    if (firstLine)
                                    {
                                        System.Console.WriteLine($"{"file1".Align(W)} | {"file2".Align(W)}");
                                        firstLine = false;
                                    }
                                    var s1 = sb1.ToString();
                                    var s2 = sb2.ToString();
                                    if (!string.IsNullOrWhiteSpace(s1) || !string.IsNullOrWhiteSpace(s2))
                                    {
                                        System.Console.WriteLine($"{s1.ToString().Align(W)} | {s2.ToString().Align(W)}");
                                    }
                                }

                                if (!sr1.EndOfStream)
                                {
                                    while (!sr1.EndOfStream)
                                    {
                                        var line1 = sr1.ReadLine();

                                        System.Console.WriteLine($"{line1.Align(W)} |");
                                    }
                                }

                                if (!sr2.EndOfStream)
                                {
                                    while (!sr2.EndOfStream)
                                    {
                                        var line2 = sr2.ReadLine();

                                        System.Console.WriteLine($"{(" ".Repeat(W))} | {line2}");
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                });

                p.Run(args);
            });
        }