From 781d010e4fb90b0aabe1f69df1b1f48bce04c03a Mon Sep 17 00:00:00 2001
From: Gerardo Grignoli <gerardog@gmail.com>
Date: Sun, 26 May 2024 04:21:54 -0300
Subject: [PATCH] Added descriptions to the config settings

---
 .../AppSettings/PathPrecedenceSetting.cs      |  3 +-
 src/gsudo/AppSettings/RegistrySetting.cs      | 12 ++--
 src/gsudo/AppSettings/Settings.cs             | 57 +++++++++++++------
 src/gsudo/Commands/ConfigCommand.cs           | 16 +++++-
 4 files changed, 64 insertions(+), 24 deletions(-)

diff --git a/src/gsudo/AppSettings/PathPrecedenceSetting.cs b/src/gsudo/AppSettings/PathPrecedenceSetting.cs
index d17b4f5b..59f2f0d1 100644
--- a/src/gsudo/AppSettings/PathPrecedenceSetting.cs
+++ b/src/gsudo/AppSettings/PathPrecedenceSetting.cs
@@ -13,7 +13,8 @@ namespace gsudo.AppSettings
     internal class PathPrecedenceSetting : RegistrySetting<bool>
     {
         public  PathPrecedenceSetting():
-            base("PathPrecedence", false, bool.Parse, RegistrySettingScope.GlobalOnly)
+            base("PathPrecedence", false, bool.Parse, RegistrySettingScope.GlobalOnly, 
+                description: "Prioritize gsudo over Microsoft Sudo in the PATH environment variable.")
         {
 
         }
diff --git a/src/gsudo/AppSettings/RegistrySetting.cs b/src/gsudo/AppSettings/RegistrySetting.cs
index b580e342..26af1d54 100644
--- a/src/gsudo/AppSettings/RegistrySetting.cs
+++ b/src/gsudo/AppSettings/RegistrySetting.cs
@@ -22,6 +22,7 @@ abstract class RegistrySetting
         public RegistrySettingScope Scope { get; protected set; }
 
         public string Name { get; set; }
+        public string Description { get; set; }
         public abstract void Save(string newValue, bool global);
         public abstract void Reset(bool global);
         public abstract object GetStringValue();
@@ -37,19 +38,20 @@ class RegistrySetting<T> : RegistrySetting
         private T runningValue;
         private bool hasValue = false;
         private readonly Func<string, T> deserializer;
-        private readonly Func<T, string> serializer;
-
-        public RegistrySetting(string name, T defaultValue, Func<string, T> deserializer, RegistrySettingScope scope = RegistrySettingScope.Any, Func<T, string> serializer = null)
-            : this(name, () => defaultValue, deserializer, scope, serializer)
+        private readonly Func<T, string> serializer;
+
+        public RegistrySetting(string name, T defaultValue, Func<string, T> deserializer, RegistrySettingScope scope = RegistrySettingScope.Any, Func<T, string> serializer = null, string description = null)
+            : this(name, () => defaultValue, deserializer, scope, serializer, description)
         { }
 
-        public RegistrySetting(string name, Func<T> defaultValue, Func<string, T> deserializer, RegistrySettingScope scope = RegistrySettingScope.Any, Func<T,string> serializer = null)
+        public RegistrySetting(string name, Func<T> defaultValue, Func<string, T> deserializer, RegistrySettingScope scope = RegistrySettingScope.Any, Func<T,string> serializer = null, string description = null)
         {
             Name = name.Replace('_', '.');
             this.defaultValue = defaultValue;
             this.deserializer = deserializer;
             this.Scope = scope;
             this.serializer = serializer;
+            this.Description = description;
         }
 
         public T Value
diff --git a/src/gsudo/AppSettings/Settings.cs b/src/gsudo/AppSettings/Settings.cs
index b4f66c93..e3be1cc5 100644
--- a/src/gsudo/AppSettings/Settings.cs
+++ b/src/gsudo/AppSettings/Settings.cs
@@ -18,85 +18,110 @@ class Settings
         public static RegistrySetting<CacheMode> CacheMode { get; set; }
             = new RegistrySetting<CacheMode>(nameof(CacheMode), CredentialsCache.CacheMode.Explicit,
                 deserializer: ExtensionMethods.ParseEnum< CacheMode>, 
-                scope: RegistrySettingScope.GlobalOnly);
+                scope: RegistrySettingScope.GlobalOnly,
+                description: "Defines how gsudo credentials cache works: Auto, Explicit (Manual), Disabled" );
 
         public static RegistrySetting<TimeSpan> CacheDuration { get; }
             = new RegistrySetting<TimeSpan>(nameof(CacheDuration), 
                 defaultValue: TimeSpan.FromSeconds(300),
                 scope: RegistrySettingScope.GlobalOnly,
                 deserializer: TimeSpanParseWithInfinite,
-                serializer: TimeSpanWithInfiniteToString
-                );
+                serializer: TimeSpanWithInfiniteToString,
+                description: "Defines how long (HH:MM:SS) the credentials cache will be valid if idle. Use 'Infinite' for no expiration");
 
         public static RegistrySetting<string> PipedPrompt { get; }
             = new RegistrySetting<string>(nameof(PipedPrompt), 
                 defaultValue: DefaultAsciiPrompt, 
-                deserializer: (s) => s
+                deserializer: (s) => s,
+                description: "Prompt to be used when gsudo uses piped mode."                
                 );
 
         public static RegistrySetting<string> Prompt { get; }
             = new RegistrySetting<string>(nameof(Prompt),
                 defaultValue: GetPromptDefaultValue, 
-                deserializer: (s) => s);
+                deserializer: (s) => s,
+                description: "Prompt to be used when gsudo uses standard mode."
+                );
 
         public static RegistrySetting<LogLevel> LogLevel { get; }
             = new RegistrySetting<LogLevel>(nameof(LogLevel), 
                 defaultValue: gsudo.LogLevel.Info, 
-                deserializer: ExtensionMethods.ParseEnum<LogLevel>);
+                deserializer: ExtensionMethods.ParseEnum<LogLevel>,
+                description: "Defines the verbosity of the log. (Valid values: All, Debug, Info, Warning, Error, None)"
+                );
 
         public static RegistrySetting<bool> ForcePipedConsole { get; }
             = new RegistrySetting<bool>(nameof(ForcePipedConsole), 
                 defaultValue: false, 
-                deserializer: bool.Parse);
+                deserializer: bool.Parse,
+                description: "Forces gsudo to use legacy piped mode. Not recommended."
+                );
 
         public static RegistrySetting<bool> ForceAttachedConsole { get; }
             = new RegistrySetting<bool>(nameof(ForceAttachedConsole), 
                 defaultValue: false, 
-                deserializer: bool.Parse);
+                deserializer: bool.Parse,
+                description: "Forces gsudo to use Attached mode. Can fix some very specific problems. Same as --attached"
+                );
 
         public static RegistrySetting<bool> ForceVTConsole { get; }
             = new RegistrySetting<bool>(nameof(ForceVTConsole), 
                 defaultValue: false, 
-                deserializer: bool.Parse);
+                deserializer: bool.Parse,
+                description: "Forces gsudo to use VT mode. Experimental. Same as --vt"
+                );
 
         public static RegistrySetting<bool> CopyEnvironmentVariables { get; }
             = new RegistrySetting<bool>(nameof(CopyEnvironmentVariables), 
                 defaultValue: false, 
-                deserializer: bool.Parse);
+                deserializer: bool.Parse,
+                description: "Only applies to Attached Mode. Forces copying caller's env variables to the elevated context. Same as --CopyEv"
+                );
 
         public static RegistrySetting<bool> CopyNetworkShares { get; } =
             new RegistrySetting<bool>(nameof(CopyNetworkShares), 
                 defaultValue: false, 
-                deserializer: bool.Parse);
+                deserializer: bool.Parse,
+                description: "Reconnect network shares on the elevated context. Same as --CopyNs"
+                );
 
         public static RegistrySetting<bool> PowerShellLoadProfile { get; } =
             new RegistrySetting<bool>(nameof(PowerShellLoadProfile), 
                 defaultValue: false, 
-                bool.Parse);
+                bool.Parse, 
+                description: "Loads the PowerShell profile when elevating PowerShell commands. Same as --LoadProfile"
+                );
 
         public static RegistrySetting<bool> SecurityEnforceUacIsolation { get; } =
             new RegistrySetting<bool>(nameof(SecurityEnforceUacIsolation), 
                 defaultValue: false, 
                 deserializer: bool.Parse,
-                scope: RegistrySettingScope.GlobalOnly);
+                scope: RegistrySettingScope.GlobalOnly,
+                description: "Elevates but with the input handle closed. More secure, less convenient. To be implemented soon also as --disableInput"
+                );
 
         public static RegistrySetting<string> ExceptionList { get; } =
             new RegistrySetting<string>(nameof(ExceptionList),
                 defaultValue: "notepad.exe;powershell.exe;whoami.exe;vim.exe;nano.exe;",
                 deserializer: (string s)=>s,
-                scope: RegistrySettingScope.GlobalOnly);
+                scope: RegistrySettingScope.GlobalOnly,
+                description: "List of executables with some issues so they will be started with \"cmd /c executable\""
+                );
 
         public static RegistrySetting<bool> NewWindow_Force { get; } =
             new RegistrySetting<bool>(nameof(NewWindow_Force),
                 defaultValue: false,
                 deserializer: bool.Parse,
-                scope: RegistrySettingScope.Any);
+                scope: RegistrySettingScope.Any,
+                description: "Always elevate in new window. Same as --new");
 
         public static RegistrySetting<CloseBehaviour> NewWindow_CloseBehaviour { get; } =
             new RegistrySetting<CloseBehaviour>(nameof(NewWindow_CloseBehaviour),
                 defaultValue: CloseBehaviour.OsDefault,
                 deserializer: ExtensionMethods.ParseEnum<CloseBehaviour>,
-                scope: RegistrySettingScope.Any);
+                scope: RegistrySettingScope.Any,
+                description: "When elevating in new window, let the window auto-close (OsDefault), KeepShellOpen or PressKeyToClose"
+                );
 
         public static RegistrySetting<bool> PathOverrideSetting = new PathPrecedenceSetting();
 
diff --git a/src/gsudo/Commands/ConfigCommand.cs b/src/gsudo/Commands/ConfigCommand.cs
index e154b22d..509ed3c4 100644
--- a/src/gsudo/Commands/ConfigCommand.cs
+++ b/src/gsudo/Commands/ConfigCommand.cs
@@ -32,11 +32,23 @@ public Task<int> Execute()
 
             if (key == null)
             {
-                // print all configs
+                // print all configs Descriptions
                 foreach (var k in Settings.AllKeys)
                 {                    
-                    var scope = k.Value.HasGlobalValue() ? "(global)" : 
+                    Console.ForegroundColor = ConsoleColor.Yellow;
+                    if (Settings.LogLevel <= LogLevel.Info)
+                    {
+                        Console.WriteLine($"# {k.Value.Name}: {k.Value.Description}");
+                    }
+                    Console.ResetColor();
+                }
+
+                // print all config values
+                foreach (var k in Settings.AllKeys)
+                {
+                    var scope = k.Value.HasGlobalValue() ? "(global)" :
                                     (k.Value.HasLocalValue() ? "(user)" : "(default)");
+
                     Console.WriteLine($"{k.Value.Name} = \"{ k.Value.GetStringValue().ToString()}\" ".PadRight(50) + scope);
                 }