diff --git a/docs/diff-tool.md b/docs/diff-tool.md index 62717df3..3a9f3eac 100644 --- a/docs/diff-tool.md +++ b/docs/diff-tool.md @@ -53,6 +53,8 @@ This value can be changed: Setting the `DiffEngine_MaxInstances` environment variable to the number of instances to launch. +This value can also be set using [the DiffEngineTray options dialog](/docs/tray.md#max-instances-to-launch). + ### Using code @@ -71,7 +73,7 @@ By default, when a diff is opened, the temp file is on the left and the target f This value can be changed by setting the `DiffEngine_TargetOnLeft` environment variable to `true`. -This value can also be set using [the DiffEngineTray options dialog](https://github.com/VerifyTests/DiffEngine/blob/main/docs/tray.md#open-on-left). +This value can also be set using [the DiffEngineTray options dialog](/docs/tray.md#open-on-left). ## Successful verification behavior diff --git a/docs/mdsource/diff-tool.source.md b/docs/mdsource/diff-tool.source.md index ee1261f1..29838fa5 100644 --- a/docs/mdsource/diff-tool.source.md +++ b/docs/mdsource/diff-tool.source.md @@ -46,6 +46,8 @@ This value can be changed: Setting the `DiffEngine_MaxInstances` environment variable to the number of instances to launch. +This value can also be set using [the DiffEngineTray options dialog](/docs/tray.md#max-instances-to-launch). + ### Using code @@ -58,7 +60,7 @@ By default, when a diff is opened, the temp file is on the left and the target f This value can be changed by setting the `DiffEngine_TargetOnLeft` environment variable to `true`. -This value can also be set using [the DiffEngineTray options dialog](https://github.com/VerifyTests/DiffEngine/blob/main/docs/tray.md#open-on-left). +This value can also be set using [the DiffEngineTray options dialog](/docs/tray.md#open-on-left). ## Successful verification behavior diff --git a/docs/mdsource/tray.source.md b/docs/mdsource/tray.source.md index 8c6c613a..1ea270f5 100644 --- a/docs/mdsource/tray.source.md +++ b/docs/mdsource/tray.source.md @@ -69,6 +69,11 @@ Runs DiffEngineTray at system startup. By default, when a diff is opened, the temp file will be on the left and the target file will be on the right. To invert this, select "Open on left". +#### Max instances to launch + +Control the [max instances to launch setting](docs/diff-tool.md#maxinstancestolaunch). + + #### Accept all HotKey Registers a system wide HotKey to accept pending: diff --git a/docs/tray.md b/docs/tray.md index 5fdcd53b..5f63743f 100644 --- a/docs/tray.md +++ b/docs/tray.md @@ -76,6 +76,11 @@ Runs DiffEngineTray at system startup. By default, when a diff is opened, the temp file will be on the left and the target file will be on the right. To invert this, select "Open on left". +#### Max instances to launch + +Control the [max instances to launch setting](docs/diff-tool.md#maxinstancestolaunch). + + #### Accept all HotKey Registers a system wide HotKey to accept pending: diff --git a/src/DiffEngine/DiffRunner.cs b/src/DiffEngine/DiffRunner.cs index ed4a7f7a..0d2fb36e 100644 --- a/src/DiffEngine/DiffRunner.cs +++ b/src/DiffEngine/DiffRunner.cs @@ -16,8 +16,7 @@ public static partial class DiffRunner public static void MaxInstancesToLaunch(int value) { - Guard.AgainstNegativeAndZero(value, nameof(value)); - MaxInstance.Set(value); + MaxInstance.SetForAppDomain(value); } public static LaunchResult Launch(DiffTool tool, string tempFile, string targetFile) diff --git a/src/DiffEngine/Guard.cs b/src/DiffEngine/Guard.cs index 75845d4c..0784b3dd 100644 --- a/src/DiffEngine/Guard.cs +++ b/src/DiffEngine/Guard.cs @@ -29,7 +29,7 @@ public static void AgainstEmpty(string value, string argumentName) } } - public static void AgainstEmpty(object[] value, string argumentName) + public static void AgainstEmpty(object?[] value, string argumentName) { if (value == null) { diff --git a/src/DiffEngine/MaxInstance.cs b/src/DiffEngine/MaxInstance.cs index cb2ca954..bc9cdfd4 100644 --- a/src/DiffEngine/MaxInstance.cs +++ b/src/DiffEngine/MaxInstance.cs @@ -3,15 +3,16 @@ static class MaxInstance { - static int maxInstancesToLaunch = GetMaxInstances(); + public static int MaxInstancesToLaunch { get; private set; } = GetMaxInstances(); static int launchedInstances; + const int defaultMax = 5; static int GetMaxInstances() { var variable = Environment.GetEnvironmentVariable("DiffEngine_MaxInstances"); if (string.IsNullOrEmpty(variable)) { - return 5; + return defaultMax; } if (ushort.TryParse(variable, out var result)) @@ -22,15 +23,35 @@ static int GetMaxInstances() throw new($"Could not parse the DiffEngine_MaxInstances environment variable: {variable}"); } - public static void Set(int value) + public static void SetForAppDomain(int value) { Guard.AgainstNegativeAndZero(value, nameof(value)); - maxInstancesToLaunch = value; + MaxInstancesToLaunch = value; + } + + public static void SetForUser(int value) + { + if (MaxInstancesToLaunch == value) + { + return; + } + MaxInstancesToLaunch = value; + string? envVariable; + if (value == defaultMax) + { + envVariable = null; + } + else + { + envVariable = value.ToString(); + } + + Environment.SetEnvironmentVariable("DiffEngine_MaxInstances", envVariable, EnvironmentVariableTarget.User); } public static bool Reached() { var instanceCount = Interlocked.Increment(ref launchedInstances); - return instanceCount > maxInstancesToLaunch; + return instanceCount > MaxInstancesToLaunch; } } \ No newline at end of file diff --git a/src/DiffEngine/ResolvedTool.cs b/src/DiffEngine/ResolvedTool.cs index f49b8616..ce9bc4e9 100644 --- a/src/DiffEngine/ResolvedTool.cs +++ b/src/DiffEngine/ResolvedTool.cs @@ -30,7 +30,7 @@ public string BuildCommand(string tempFile, string targetFile) string GetArguments(string tempFile, string targetFile) { - if (TargetPositionHelper.TargetOnLeft) + if (TargetPosition.TargetOnLeft) { return TargetLeftArguments(tempFile, targetFile); } diff --git a/src/DiffEngine/TargetPositionHelper.cs b/src/DiffEngine/TargetPosition.cs similarity index 88% rename from src/DiffEngine/TargetPositionHelper.cs rename to src/DiffEngine/TargetPosition.cs index 6ca02f7d..e7241dc1 100644 --- a/src/DiffEngine/TargetPositionHelper.cs +++ b/src/DiffEngine/TargetPosition.cs @@ -1,10 +1,10 @@ using System; -static class TargetPositionHelper +static class TargetPosition { public static bool TargetOnLeft { get; private set; } - static TargetPositionHelper() + static TargetPosition() { TargetOnLeft = ReadTargetOnLeft().GetValueOrDefault(false); } @@ -33,6 +33,11 @@ static TargetPositionHelper() public static void SetTargetOnLeft(bool value) { + if (TargetOnLeft == value) + { + return; + } + TargetOnLeft = value; string? envVariable; if (value) diff --git a/src/DiffEngineTray.Tests/OptionsFormTests.Default.verified.png b/src/DiffEngineTray.Tests/OptionsFormTests.Default.verified.png index 39331afb..9051f6fe 100644 Binary files a/src/DiffEngineTray.Tests/OptionsFormTests.Default.verified.png and b/src/DiffEngineTray.Tests/OptionsFormTests.Default.verified.png differ diff --git a/src/DiffEngineTray.Tests/OptionsFormTests.WithKeys.verified.png b/src/DiffEngineTray.Tests/OptionsFormTests.WithKeys.verified.png index 971c787a..f96ddd39 100644 Binary files a/src/DiffEngineTray.Tests/OptionsFormTests.WithKeys.verified.png and b/src/DiffEngineTray.Tests/OptionsFormTests.WithKeys.verified.png differ diff --git a/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt b/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt index 90191a1f..390dfe51 100644 --- a/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt +++ b/src/DiffEngineTray.Tests/SettingsHelperTests.ReadWrite.verified.txt @@ -1,5 +1,6 @@ -{ +{ AcceptAllHotKey: { Key: T - } + }, + MaxInstancesToLaunch: 5 } \ No newline at end of file diff --git a/src/DiffEngineTray/DiffEngineTray.csproj b/src/DiffEngineTray/DiffEngineTray.csproj index 36382d1b..207a8a01 100644 --- a/src/DiffEngineTray/DiffEngineTray.csproj +++ b/src/DiffEngineTray/DiffEngineTray.csproj @@ -28,7 +28,9 @@ - + + + diff --git a/src/DiffEngineTray/Settings/OptionsForm.Designer.cs b/src/DiffEngineTray/Settings/OptionsForm.Designer.cs index 3417aa5f..e3d83701 100644 --- a/src/DiffEngineTray/Settings/OptionsForm.Designer.cs +++ b/src/DiffEngineTray/Settings/OptionsForm.Designer.cs @@ -26,9 +26,14 @@ void InitializeComponent() this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.updateButton = new System.Windows.Forms.Button(); this.targetOnLeftCheckBox = new System.Windows.Forms.CheckBox(); + this.maxInstancesGroupBox = new System.Windows.Forms.GroupBox(); + this.maxInstancesNumericUpDown = new System.Windows.Forms.NumericUpDown(); + this.label1 = new System.Windows.Forms.Label(); this.bottomPanel.SuspendLayout(); this.groupBox1.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); + this.maxInstancesGroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.maxInstancesNumericUpDown)).BeginInit(); this.SuspendLayout(); // // bottomPanel @@ -38,17 +43,17 @@ void InitializeComponent() this.bottomPanel.Controls.Add(this.save); this.bottomPanel.Dock = System.Windows.Forms.DockStyle.Bottom; this.bottomPanel.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; - this.bottomPanel.Location = new System.Drawing.Point(5, 451); + this.bottomPanel.Location = new System.Drawing.Point(5, 508); this.bottomPanel.Margin = new System.Windows.Forms.Padding(2); this.bottomPanel.Name = "bottomPanel"; - this.bottomPanel.Size = new System.Drawing.Size(471, 29); + this.bottomPanel.Size = new System.Drawing.Size(507, 29); this.bottomPanel.TabIndex = 1; // // cancel // this.cancel.AutoSize = true; this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancel.Location = new System.Drawing.Point(389, 2); + this.cancel.Location = new System.Drawing.Point(425, 2); this.cancel.Margin = new System.Windows.Forms.Padding(2); this.cancel.Name = "cancel"; this.cancel.RightToLeft = System.Windows.Forms.RightToLeft.Yes; @@ -60,7 +65,7 @@ void InitializeComponent() // save // this.save.AutoSize = true; - this.save.Location = new System.Drawing.Point(305, 2); + this.save.Location = new System.Drawing.Point(341, 2); this.save.Margin = new System.Windows.Forms.Padding(2); this.save.Name = "save"; this.save.Size = new System.Drawing.Size(80, 25); @@ -76,11 +81,11 @@ void InitializeComponent() this.acceptAllHotKey.Help = "Accept pending deletes and pending moves"; this.acceptAllHotKey.HotKey = null; this.acceptAllHotKey.Label = "Accept all HotKey"; - this.acceptAllHotKey.Location = new System.Drawing.Point(5, 58); + this.acceptAllHotKey.Location = new System.Drawing.Point(5, 140); this.acceptAllHotKey.Margin = new System.Windows.Forms.Padding(2); this.acceptAllHotKey.Name = "acceptAllHotKey"; this.acceptAllHotKey.Padding = new System.Windows.Forms.Padding(3); - this.acceptAllHotKey.Size = new System.Drawing.Size(471, 114); + this.acceptAllHotKey.Size = new System.Drawing.Size(507, 114); this.acceptAllHotKey.TabIndex = 2; this.acceptAllHotKey.TabStop = false; // @@ -92,7 +97,7 @@ void InitializeComponent() this.startupCheckBox.Margin = new System.Windows.Forms.Padding(2); this.startupCheckBox.Name = "startupCheckBox"; this.startupCheckBox.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); - this.startupCheckBox.Size = new System.Drawing.Size(471, 27); + this.startupCheckBox.Size = new System.Drawing.Size(507, 27); this.startupCheckBox.TabIndex = 3; this.startupCheckBox.Text = "Run at startup"; this.startupCheckBox.UseVisualStyleBackColor = true; @@ -104,10 +109,10 @@ void InitializeComponent() this.groupBox1.Controls.Add(this.trayDocsLink); this.groupBox1.Controls.Add(this.diffEngineLink); this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top; - this.groupBox1.Location = new System.Drawing.Point(5, 316); + this.groupBox1.Location = new System.Drawing.Point(5, 398); this.groupBox1.Name = "groupBox1"; this.groupBox1.Padding = new System.Windows.Forms.Padding(6, 5, 6, 5); - this.groupBox1.Size = new System.Drawing.Size(471, 89); + this.groupBox1.Size = new System.Drawing.Size(507, 89); this.groupBox1.TabIndex = 5; this.groupBox1.TabStop = false; this.groupBox1.Text = "More information:"; @@ -158,11 +163,11 @@ void InitializeComponent() " Rider, or Visual Studio Code."; this.acceptOpenHotKey.HotKey = null; this.acceptOpenHotKey.Label = "Accept all open HotKey"; - this.acceptOpenHotKey.Location = new System.Drawing.Point(5, 172); + this.acceptOpenHotKey.Location = new System.Drawing.Point(5, 254); this.acceptOpenHotKey.Margin = new System.Windows.Forms.Padding(2); this.acceptOpenHotKey.Name = "acceptOpenHotKey"; this.acceptOpenHotKey.Padding = new System.Windows.Forms.Padding(3); - this.acceptOpenHotKey.Size = new System.Drawing.Size(471, 144); + this.acceptOpenHotKey.Size = new System.Drawing.Size(507, 144); this.acceptOpenHotKey.TabIndex = 6; this.acceptOpenHotKey.TabStop = false; // @@ -171,11 +176,11 @@ void InitializeComponent() this.flowLayoutPanel1.AutoSize = true; this.flowLayoutPanel1.Controls.Add(this.updateButton); this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top; - this.flowLayoutPanel1.Location = new System.Drawing.Point(5, 405); + this.flowLayoutPanel1.Location = new System.Drawing.Point(5, 487); this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(2); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; this.flowLayoutPanel1.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.flowLayoutPanel1.Size = new System.Drawing.Size(471, 33); + this.flowLayoutPanel1.Size = new System.Drawing.Size(507, 33); this.flowLayoutPanel1.TabIndex = 7; // // updateButton @@ -198,10 +203,54 @@ void InitializeComponent() this.targetOnLeftCheckBox.Margin = new System.Windows.Forms.Padding(2); this.targetOnLeftCheckBox.Name = "targetOnLeftCheckBox"; this.targetOnLeftCheckBox.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); - this.targetOnLeftCheckBox.Size = new System.Drawing.Size(471, 27); + this.targetOnLeftCheckBox.Size = new System.Drawing.Size(507, 27); this.targetOnLeftCheckBox.TabIndex = 8; this.targetOnLeftCheckBox.Text = "Open target on left. The default is temp on left and target on right"; this.targetOnLeftCheckBox.UseVisualStyleBackColor = true; + // + // maxInstancesGroupBox + // + this.maxInstancesGroupBox.Controls.Add(this.maxInstancesNumericUpDown); + this.maxInstancesGroupBox.Controls.Add(this.label1); + this.maxInstancesGroupBox.Dock = System.Windows.Forms.DockStyle.Top; + this.maxInstancesGroupBox.Location = new System.Drawing.Point(5, 58); + this.maxInstancesGroupBox.Name = "maxInstancesGroupBox"; + this.maxInstancesGroupBox.Padding = new System.Windows.Forms.Padding(5); + this.maxInstancesGroupBox.Size = new System.Drawing.Size(507, 82); + this.maxInstancesGroupBox.TabIndex = 9; + this.maxInstancesGroupBox.TabStop = false; + this.maxInstancesGroupBox.Text = "Max instances to launch"; + // + // maxInstancesNumericUpDown + // + this.maxInstancesNumericUpDown.Dock = System.Windows.Forms.DockStyle.Left; + this.maxInstancesNumericUpDown.Location = new System.Drawing.Point(5, 44); + this.maxInstancesNumericUpDown.Margin = new System.Windows.Forms.Padding(5); + this.maxInstancesNumericUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.maxInstancesNumericUpDown.Name = "maxInstancesNumericUpDown"; + this.maxInstancesNumericUpDown.Size = new System.Drawing.Size(62, 23); + this.maxInstancesNumericUpDown.TabIndex = 0; + this.maxInstancesNumericUpDown.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Dock = System.Windows.Forms.DockStyle.Top; + this.label1.Location = new System.Drawing.Point(5, 21); + this.label1.Name = "label1"; + this.label1.Padding = new System.Windows.Forms.Padding(3, 3, 3, 5); + this.label1.Size = new System.Drawing.Size(473, 23); + this.label1.TabIndex = 1; + this.label1.Text = "To minimize the impact on system resources, the maximum diffs to launch is restri" + + "cted."; // // OptionsForm // @@ -210,12 +259,13 @@ void InitializeComponent() this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.CancelButton = this.cancel; - this.ClientSize = new System.Drawing.Size(481, 484); + this.ClientSize = new System.Drawing.Size(517, 541); this.Controls.Add(this.flowLayoutPanel1); this.Controls.Add(this.groupBox1); this.Controls.Add(this.bottomPanel); this.Controls.Add(this.acceptOpenHotKey); this.Controls.Add(this.acceptAllHotKey); + this.Controls.Add(this.maxInstancesGroupBox); this.Controls.Add(this.targetOnLeftCheckBox); this.Controls.Add(this.startupCheckBox); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; @@ -233,6 +283,9 @@ void InitializeComponent() this.groupBox1.PerformLayout(); this.flowLayoutPanel1.ResumeLayout(false); this.flowLayoutPanel1.PerformLayout(); + this.maxInstancesGroupBox.ResumeLayout(false); + this.maxInstancesGroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.maxInstancesNumericUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -250,4 +303,7 @@ void InitializeComponent() private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Button updateButton; private System.Windows.Forms.CheckBox targetOnLeftCheckBox; + private System.Windows.Forms.GroupBox maxInstancesGroupBox; + private System.Windows.Forms.NumericUpDown maxInstancesNumericUpDown; + private System.Windows.Forms.Label label1; } \ No newline at end of file diff --git a/src/DiffEngineTray/Settings/OptionsForm.cs b/src/DiffEngineTray/Settings/OptionsForm.cs index 7fa8da72..ed066196 100644 --- a/src/DiffEngineTray/Settings/OptionsForm.cs +++ b/src/DiffEngineTray/Settings/OptionsForm.cs @@ -25,6 +25,7 @@ public OptionsForm(Settings settings, Func> acceptOpenHotKey.HotKey = settings.AcceptOpenHotKey; startupCheckBox.Checked = settings.RunAtStartup; targetOnLeftCheckBox.Checked = settings.TargetOnLeft; + maxInstancesNumericUpDown.Value = settings.MaxInstancesToLaunch; } async void save_Click(object sender, EventArgs e) @@ -34,7 +35,8 @@ async void save_Click(object sender, EventArgs e) TargetOnLeft = targetOnLeftCheckBox.Checked, RunAtStartup = startupCheckBox.Checked, AcceptAllHotKey = acceptAllHotKey.HotKey, - AcceptOpenHotKey = acceptOpenHotKey.HotKey + AcceptOpenHotKey = acceptOpenHotKey.HotKey, + MaxInstancesToLaunch = (int)maxInstancesNumericUpDown.Value }; var errors = (await trySave(newSettings)).ToList(); diff --git a/src/DiffEngineTray/Settings/Settings.cs b/src/DiffEngineTray/Settings/Settings.cs index 16db46fc..f9ff1e11 100644 --- a/src/DiffEngineTray/Settings/Settings.cs +++ b/src/DiffEngineTray/Settings/Settings.cs @@ -4,4 +4,5 @@ public class Settings public HotKey? AcceptOpenHotKey { get; set; } public bool RunAtStartup { get; set; } public bool TargetOnLeft { get; set; } + public int MaxInstancesToLaunch { get; set; } = MaxInstance.MaxInstancesToLaunch; } \ No newline at end of file diff --git a/src/DiffEngineTray/Settings/SettingsHelper.cs b/src/DiffEngineTray/Settings/SettingsHelper.cs index e7d506c5..d28fa46c 100644 --- a/src/DiffEngineTray/Settings/SettingsHelper.cs +++ b/src/DiffEngineTray/Settings/SettingsHelper.cs @@ -29,13 +29,15 @@ public static async Task Read() settings = new(); } - settings.TargetOnLeft = TargetPositionHelper.TargetOnLeft; + settings.TargetOnLeft = TargetPosition.TargetOnLeft; + settings.MaxInstancesToLaunch = MaxInstance.MaxInstancesToLaunch; return settings; } public static async Task Write(Settings settings) { - TargetPositionHelper.SetTargetOnLeft(settings.TargetOnLeft); + TargetPosition.SetTargetOnLeft(settings.TargetOnLeft); + MaxInstance.SetForUser(settings.MaxInstancesToLaunch); File.Delete(FilePath); await using var stream = File.OpenWrite(FilePath); await JsonSerializer.SerializeAsync(stream, settings); diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 66a112ef..65dad285 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,7 +2,7 @@ CS1591;CS0649 - 7.0.0 + 7.1.0 1.0.0 Testing, Snapshot, Diff, Compare Launches diff tools based on file extensions. Designed to be consumed by snapshot testing libraries.