public CommandResult <List <DriveInfo> > Driveinfo(
            CommandEvaluationContext context,
            [Parameter("drive name for which informations must be printed. if no drive specified, list all drives", true)] string drive,
            [Option("b", "borders", "if set add table borders")] bool borders
            )
        {
            var drives = DriveInfo.GetDrives().AsQueryable();

            if (drive != null)
            {
                drives = drives.Where(x => x.Name.Equals(drive, CommandLineParser.SyntaxMatchingRule));
                if (drives.Count() == 0)
                {
                    context.Errorln($"drive \"{drive}\" not found");
                }
            }
            var table = new DataTable();

            table.AddColumns("name", "label", "type", "format", "bytes");
            foreach (var di in drives)
            {
                var f   = DefaultForegroundCmd;
                var row = table.NewRow();
                try
                {
                    row["name"]   = $"{context.ShellEnv.Colors.Highlight}{di.Name}{f}";
                    row["label"]  = $"{context.ShellEnv.Colors.Highlight}{di.VolumeLabel}{f}";
                    row["type"]   = $"{context.ShellEnv.Colors.Name}{di.DriveType}{f}";
                    row["format"] = $"{context.ShellEnv.Colors.Name}{di.DriveFormat}{f}";
                    row["bytes"]  = (di.TotalSize == 0) ? "" : $"{HumanFormatOfSize(di.TotalFreeSpace, 2, " ", context.ShellEnv.Colors.Numeric.ToString(), f)}{f}/{context.ShellEnv.Colors.Numeric}{HumanFormatOfSize(di.TotalSize, 2, " ", context.ShellEnv.Colors.Numeric.ToString(), f)} {f}({context.ShellEnv.Colors.Highlight}{Math.Round((double)di.TotalFreeSpace / (double)di.TotalSize * 100d, 2)}{f} %)";
                }
                catch (UnauthorizedAccessException)
                {
                    context.Errorln($"unauthorized access to drive {di.Name}");
                    row["name"]   = $"{context.ShellEnv.Colors.Highlight}{di.Name}{f}";
                    row["label"]  = "?";
                    row["type"]   = "?";
                    row["format"] = "?";
                    row["bytes"]  = "?";
                }
                catch (Exception ex)
                {
                    context.Errorln($"error when accessing drive {di.Name}: {ex.Message}");
                    row["name"]   = $"{context.ShellEnv.Colors.Highlight}{di.Name}{f}";
                    row["label"]  = "?";
                    row["type"]   = "?";
                    row["format"] = "?";
                    row["bytes"]  = "?";
                }
                table.Rows.Add(row);
            }
            table.Echo(
                new EchoEvaluationContext(context.Out, context,
                                          new TableFormattingOptions(context.ShellEnv.GetValue <TableFormattingOptions>(ShellEnvironmentVar.display_tableFormattingOptions))
            {
                NoBorders = !borders
            }));

            return(new CommandResult <List <DriveInfo> >(drives.ToList()));
        }
Example #2
0
        Exception LogInternal(string text, string logPrefix = "INF")
        {
            var str = $"{logPrefix} [{Process.GetCurrentProcess().ProcessName}:{Process.GetCurrentProcess().Id},{Thread.CurrentThread.Name}:{Thread.CurrentThread.ManagedThreadId}] {System.DateTime.Now}.{System.DateTime.Now.Millisecond} | {text}";

            lock (_logFileLock)
            {
                try
                {
                    File.AppendAllLines(CommandEvaluationContext.CommandLineProcessor.Settings.LogFilePath, new List <string> {
                        str
                    });
                    return(null);
                }
                catch (Exception logAppendAllLinesException)
                {
                    if (!MuteLogErrors)
                    {
                        if (CommandEvaluationContext.CommandLineProcessor.Settings.LogAppendAllLinesErrorIsEnabled)
                        {
                            CommandEvaluationContext.Errorln(logAppendAllLinesException.Message);
                        }
                    }
                    return(logAppendAllLinesException);
                }
            }
        }
 public CommandResult <DirectoryPath> Cd(
     CommandEvaluationContext context,
     [Parameter("path where to list files and folders. if not specified is equal to the current directory", true)] DirectoryPath path
     )
 {
     path ??= new DirectoryPath(Path.GetPathRoot(Environment.CurrentDirectory));
     if (path.CheckExists(context))
     {
         var bkpath = Environment.CurrentDirectory;
         try
         {
             Environment.CurrentDirectory = path.FullName;
         }
         catch (UnauthorizedAccessException)
         {
             context.Errorln($"unauthorized access to {path.PrintableFullName}");
             Environment.CurrentDirectory = bkpath;
             return(new CommandResult <DirectoryPath>(path, ReturnCode.Error));
         }
         return(new CommandResult <DirectoryPath>(path, ReturnCode.OK));
     }
     else
     {
         return(new CommandResult <DirectoryPath>(path, ReturnCode.Error));
     }
 }
Example #4
0
 public CommandResult <List <TextFileInfo> > More(
     CommandEvaluationContext context,
     [Parameter("file or folder path")] WildcardFilePath path,
     [Option("h", "hide-line-numbers", "hide line numbers")] bool hideLineNumbers,
     [Option("r", "raw", "turn on raw output")] bool raw
     )
 {
     if (path.CheckExists(context))
     {
         var counts = new FindCounts();
         var items  = FindItems(context, path.FullName, path.WildCardFileName ?? "*", true, false, false, true, false, null, false, counts, false, false);
         var r      = new List <TextFileInfo>();
         foreach (var item in items)
         {
             PrintFile(context, (FilePath)item, hideLineNumbers, raw);
             r.Add(new TextFileInfo((FilePath)item, null, OSPlatform.Create("?"), null));
         }
         if (items.Count == 0)
         {
             context.Errorln($"more: no such file: {path.OriginalPath}");
             return(new CommandResult <List <TextFileInfo> >(new List <TextFileInfo> {
                 new TextFileInfo(new FilePath(path.OriginalPath), null, OSPlatform.Create("?"), null)
             }, ReturnCode.Error));
         }
         context.Out.ShowCur();
         return(new CommandResult <List <TextFileInfo> >(r));
     }
     else
     {
         return(new CommandResult <List <TextFileInfo> >(new List <TextFileInfo> {
             new TextFileInfo(new FilePath(path.FullName), null, OSPlatform.Create("?"), null)
         }, ReturnCode.Error));
     }
 }
        public CommandResult <string> NugetDownload(
            CommandEvaluationContext context,
            [Parameter(0, "package (.nuget) ID")] string id,
            [Parameter(1, "package version")] string ver,
            [Option("o", "output", "output path", true, true)] string @out = ".",
            [Option("u", "download-url", "nuget server api query service template url", true, true)] string url = DownloadUrl
            )
        {
            id  = id.Trim().ToLower();
            ver = ver.ToLower();
            var queryString = url
                              .Replace("{LOWER_ID}", id)
                              .Replace("{LOWER_VERSION}", ver);

            context.Out.Echo(context.ShellEnv.Colors.Log + $"GET {queryString} ... ");

            using var httpClient = new HttpClient();
            using var request    = new HttpRequestMessage(new HttpMethod("GET"), queryString);

            var tsk    = httpClient.SendAsync(request);
            var result = tsk.Result;

            if (result.IsSuccessStatusCode)
            {
                var str = result.Content.ReadAsStreamAsync().Result;

                context.Out.Echoln(" Done(rdc)");
                context.Out.Echo(ANSI.RSTXTA + ANSI.CPL(1) + ANSI.EL(ANSI.ELParameter.p2));     // TODO: add as ANSI combo

                if (str == null)
                {
                    context.Warning("result is empty");
                }
                else
                {
                    var fn = $"{id}.{ver}.nupkg";
                    @out           = Path.Combine(@out, fn);
                    using var fstr = new FileStream(@out, FileMode.Create, FileAccess.Write);
                    int b;
                    while ((b = str.ReadByte()) != -1)
                    {
                        fstr.WriteByte((byte)b);
                    }
                    str.Close();
                    fstr.Close();
                    context.Out.Echoln($"package '{fn}' has been downloaded to: {new FilePath(@out)}");

                    return(new CommandResult <string>(@out));
                }
            }
            else
            {
                context.Errorln($"can't get response content: {result.ReasonPhrase}");
                return(new CommandResult <string>(ReturnCode.Error));
            }

            return(new CommandResult <string>(ReturnCode.Error));
        }
        public CommandResult <HttpContentBody> Get(
            CommandEvaluationContext context,
            [Parameter("query string")] string queryString,
            [Option("q", "quiet", "if not set (default), output get result on stdout", false, true)] bool quiet = false,
            [Option("b", "bin", "get as a binary stream", false, true)] bool binary = false
            )
        {
            object @return = null;

            if (string.IsNullOrWhiteSpace(queryString))
            {
                context.Errorln("uri must not be empty");
                return(new CommandResult <HttpContentBody>(HttpContentBody.EmptyHttpContentBody));
            }
            if (!queryString.ToLower().StartsWith("http://") && !queryString.ToLower().StartsWith("https://"))
            {
                queryString = "http://" + queryString;
            }

            using (var httpClient = new HttpClient())
            {
                using var request = new HttpRequestMessage(new HttpMethod("GET"), queryString);
                var tsk    = httpClient.SendAsync(request);
                var result = tsk.Result;
                if (result.IsSuccessStatusCode)
                {
                    //@return = result.Content.ReadAsStringAsync().Result;
                    @return =
                        !binary?
                        result.Content.ReadAsStringAsync().Result:
                        result.Content.ReadAsByteArrayAsync().Result;

                    if (!quiet)
                    {
                        context.Out.Echo(@return, true, true);
                    }
                }
                else
                {
                    context.Errorln($"can't get response content: {result.ReasonPhrase}");
                }
            }

            return(new CommandResult <HttpContentBody>(new HttpContentBody(@return)));
        }
        public CommandResult <Encoding> Encoding(
            CommandEvaluationContext context,
            [Parameter(0, "encoding name", true)] string encodingName
            )
        {
            var      setEncoding = !string.IsNullOrWhiteSpace(encodingName);
            var      e           = System.Console.OutputEncoding;
            Encoding ret         = e;

            var @out = context.Out;

            void echokv(string name, object value)
            {
                new KeyValuePair <string, object>(name, value).Echo(new EchoEvaluationContext(@out, context));
            };

            if (setEncoding)
            {
                try
                {
                    var ne = System.Text.Encoding.GetEncoding(encodingName);
                    System.Console.OutputEncoding = ne;
                    ret = ne;
                }
                catch (ArgumentException)
                {
                    context.Errorln($"encoding not found: '{encodingName}'");
                    setEncoding = true;
                }
            }
            else
            {
                echokv("name", e.EncodingName);
                echokv(" code page", e.CodePage);
            }

            if (!setEncoding)
            {
                @out.Echoln();
                @out.Echoln($"{Br}{Uon}available encodings are:{Tdoff}{Br}");

                var lst = new List <object>(System.Text.Encoding.GetEncodings());
                foreach (var o in lst)
                {
                    if (o is EncodingInfo encoding)
                    {
                        echokv("name", encoding.Name);
                        echokv(" code page", encoding.CodePage);
                        @out.Echoln();
                    }
                }
            }
            return(new CommandResult <Encoding>(ret));
        }
Example #8
0
 public void UnsetAlias(CommandEvaluationContext context, string name)
 {
     if (_aliases.ContainsKey(name))
     {
         _aliases.Remove(name);
     }
     else
     {
         context.Errorln($"can't unset alias '{name}' because it is not defined");
     }
 }
Example #9
0
 public virtual bool CheckExists(CommandEvaluationContext context, bool dumpError = true)
 {
     if (!FileSystemInfo.Exists)
     {
         if (dumpError)
         {
             context.Errorln($"path doesn't exists: {this}");
         }
         return(false);
     }
     return(true);
 }
Example #10
0
 public bool CheckPathExists(CommandEvaluationContext context, bool dumpError = true)
 {
     if (!Directory.Exists(Path.GetDirectoryName(FullName)))
     {
         if (dumpError)
         {
             context.Errorln($"the directory of the file doesn't exists: {this}");
         }
         return(false);
     }
     return(true);
 }
 public override bool CheckExists(CommandEvaluationContext context, bool dumpError = true)
 {
     if (!DirectoryInfo.Exists)
     {
         if (dumpError)
         {
             context.Errorln($"file or directory doesn't exists: {this}");
         }
         return(false);
     }
     return(true);
 }
Example #12
0
        public CommandResult <HttpContentBody> Get(
            CommandEvaluationContext context,
            [Parameter("query string")] string queryString
            )
        {
            string @return = null;

            if (string.IsNullOrWhiteSpace(queryString))
            {
                context.Errorln("uri must not be empty");
                return(new CommandResult <HttpContentBody>(HttpContentBody.EmptyHttpContentBody));
            }
            if (!queryString.ToLower().StartsWith("http://") && !queryString.ToLower().StartsWith("https://"))
            {
                queryString = "http://" + queryString;
            }

            using (var httpClient = new HttpClient())
            {
                using var request = new HttpRequestMessage(new HttpMethod("GET"), queryString);
                var tsk    = httpClient.SendAsync(request);
                var result = tsk.Result;
                if (result.IsSuccessStatusCode)
                {
                    @return = result.Content.ReadAsStringAsync().Result;

                    context.Out.Echo(@return, true, true);
                }
                else
                {
                    context.Errorln($"can't get response content: {result.ReasonPhrase}");
                }
            }

            return(new CommandResult <HttpContentBody>(new HttpContentBody(@return)));
        }
        public CommandResult <PackageVersions> NugetVer(
            CommandEvaluationContext context,
            [Parameter(0, "package (.nuget) ID")] string id,
            [Option("q", "quiet", "mute output of result")] bool quiet = false,
            [Option("u", "get-url", "nuget server api query service template url", true, true)] string url = GetVerUrl
            )
        {
            var queryString = url.Replace("{ID}", id.Trim());

            context.Out.Echo(context.ShellEnv.Colors.Log + $"GET {queryString} ... ");

            using var httpClient = new HttpClient();
            using var request    = new HttpRequestMessage(new HttpMethod("GET"), queryString);

            var tsk    = httpClient.SendAsync(request);
            var result = tsk.Result;

            if (result.IsSuccessStatusCode)
            {
                var res = result.Content.ReadAsStringAsync().Result;

                context.Out.Echoln(" Done(rdc)");
                context.Out.Echo(ANSI.RSTXTA + ANSI.CPL(1) + ANSI.EL(ANSI.ELParameter.p2));     // TODO: add as ANSI combo

                if (res != null && !string.IsNullOrWhiteSpace(res))
                {
                    if (!quiet)
                    {
                        context.Out.Echoln(res);
                    }

                    var obj = JsonConvert.DeserializeObject <PackageVersions>(res);

                    return(new CommandResult <PackageVersions>(obj));
                }
                else
                {
                    context.Warning("result is empty");
                }
            }
            else
            {
                context.Errorln($"can't get response content: {result.ReasonPhrase}");
            }

            return(new CommandResult <PackageVersions>(null));
        }
Example #14
0
        void LoadModulesFromConfig(CommandEvaluationContext context)
        {
            var mods = ModuleUtil.LoadModuleInitConfiguration(context);

            if (mods == null)
            {
                // rebuild the module-init file - it is crashed
                mods = new ModuleInit()
                {
                    ReadMe = $"new file generated on {System.DateTime.Now}",
                    List   = Array.Empty <ModuleInitItem>()
                };
                ModuleUtil.SaveModuleInitConfiguration(context, mods);
                context.Errorln("a crashed version of module-init has been restored to initial state");
            }

            var enabledMods = mods.List.Where(x => x.IsEnabled);

            if (!enabledMods.Any())
            {
                return;
            }
            var o = context.Out;

            o.Echoln();
            foreach (var mod in enabledMods)
            {
                try
                {
                    context.Logger.Info(_clp.CommandEvaluationContext.ShellEnv.Colors.Log + $"loading module: '{mod.Path}' ... ", true, false);
                    var a = Assembly.LoadFile(mod.Path);
                    context.Logger.Info(_clp.CommandEvaluationContext.ShellEnv.Colors.Log + $"module assembly loaded: '{a}'. registering module ... ", true, false);
                    var modSpec = _clp.ModuleManager.RegisterModule(_clp.CommandEvaluationContext, a);
                    context.Logger.Done(modSpec.Info.GetDescriptor(context));
                }
                catch (Exception loadModException)
                {
                    _clp.CommandEvaluationContext.Logger.Fail(loadModException);
                }
            }
        }
Example #15
0
        public static ExpressionEvaluationResult RunWorkUnit(
            CommandEvaluationContext context,
            PipelineParseResult pipelineParseResult
            )
        {
            var syntaxParsingResult = pipelineParseResult.ParseResult.SyntaxParsingResults.First();

            try
            {
                // capture the err output
                context.Err.StartRecording();

                var r          = InvokeCommand(context, syntaxParsingResult.CommandSyntax.CommandSpecification, syntaxParsingResult.MatchingParameters);
                var res        = r as ICommandResult;
                var err_record = context.Err.StopRecording();
                var err        = res.ExecErrorText;

                // auto assign from Err stream if no error text provided
                if (string.IsNullOrEmpty(res.ExecErrorText) && !string.IsNullOrEmpty(err_record))
                {
                    err = err_record;
                }

                return
                    ((res == null)?
                     new ExpressionEvaluationResult(pipelineParseResult.Expr, null, ParseResultType.Valid, null, (int)ReturnCode.Error, null, "the command has returned a null result") :
                     new ExpressionEvaluationResult(pipelineParseResult.Expr, null, ParseResultType.Valid, res.GetOuputData(), res.ReturnCode, null, err));
            }
            catch (Exception commandInvokeError)
            {
                // error is catched at shell level
                var commandError = commandInvokeError.InnerException ?? commandInvokeError;
                context.Errorln(commandError.Message);
                return(new ExpressionEvaluationResult(pipelineParseResult.Expr, null, pipelineParseResult.ParseResult.ParseResultType, null, (int)ReturnCode.Error, commandError));
            }
            finally {
                context.Err.StopRecording();
            }
        }
        public CommandResult <string> HistoryPreviousCommand(
            CommandEvaluationContext context,
            [Parameter("line number in the command history list if positive, else current command minus n if negative (! -1 equivalent to !!)")] int n
            )
        {
            var    h     = context.CommandLineProcessor.CmdsHistory.History;
            var    index = (n < 0) ? h.Count + n : n - 1;
            string lastCmd;

            if (index < 0 || index >= h.Count)
            {
                context.Errorln($"line number out of bounds of commands history list (1..{h.Count})");
                return(new CommandResult <string>(ReturnCode.Error));
            }
            else
            {
                lastCmd = h[index];
                context.CommandLineProcessor.AssertCommandLineProcessorHasACommandLineReader();
                context.CommandLineProcessor.CommandLineReader.SendNextInput(lastCmd);
            }
            return(new CommandResult <string>(lastCmd));
        }
Example #17
0
        UnregisterModuleCommands(
            CommandEvaluationContext context,
            string moduleName)
        {
            var moduleSpecification = _modules.Values.Where(x => x.Name == moduleName).FirstOrDefault();

            if (moduleSpecification != null)
            {
                foreach (var com in AllCommands)
                {
                    if (com.MethodInfo.DeclaringType.Assembly == moduleSpecification.Assembly)
                    {
                        UnregisterCommand(com);
                    }
                }
                return(moduleSpecification);
            }
            else
            {
                context.Errorln($"commands module '{moduleName}' not registered");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }
        }
Example #18
0
 void DisplayEditor()
 {
     try
     {
         lock (Console.ConsoleLock)
         {
             Context.Out.HideCur();
             Context.Out.ClearScreen();
             _width  = sc.WindowWidth;
             _height = sc.WindowHeight;
             ComputeBarVisible();
             SetCursorHome();
             DisplayFile();
             EmptyInfoBar();
             DisplayInfoBar(false);
             Context.Out.SetCursorPos(_X, _Y);
             Context.Out.ShowCur();
         }
     }
     catch (Exception ex)
     {
         Context.Errorln(ex + "");
     }
 }
Example #19
0
 CommandResult <List <ModuleSpecification> > _ModuleErr(CommandEvaluationContext context, string reason)
 {
     context?.Errorln(reason);
     return(new CommandResult <List <ModuleSpecification> >(ReturnCode.Error, reason));
 }
Example #20
0
        public ModuleSpecification RegisterModule(
            CommandEvaluationContext context,
            Assembly assembly)
        {
            ModuleSpecification moduleSpecification;

            var moduleAttr = assembly.GetCustomAttribute <ShellModuleAttribute>();

            if (moduleAttr == null)
            {
                context.Errorln($"assembly is not a shell module: '{assembly.FullName}'");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }

            var id = assembly.GetCustomAttribute <AssemblyTitleAttribute>()?.Title ??
                     throw new Exception($"module id missing in assembly '{assembly.ManifestModule.Name}' ('AssemblyTitle' attribute missing)");
            var ver = assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion ??
                      throw new Exception($"module version missing in assembly '{assembly.ManifestModule.Name}' ('AssemblyInformationalVersion' attribute missing)");
            var modKey = GetModuleLowerId(id, ver);

            if (_modules.ContainsKey(modKey))
            {
                context.Errorln($"module already registered: {modKey} (path={assembly.FullName})");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }

            var typesCount  = 0;
            var comTotCount = 0;
            var hooksCount  = 0;

            foreach (var type in assembly.GetTypes())
            {
                // register hooks

                var hookAttr = type.GetCustomAttribute <HooksAttribute>();
                if (hookAttr != null)
                {
                    // module,class owns hooks
                    foreach (var mi in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                    {
                        var hook = mi.GetCustomAttribute <HookAttribute>();
                        if (hook != null)
                        {
                            ModuleHookManager.RegisterHook(context, hook.HookName, mi);
                            hooksCount++;
                        }
                    }
                }

                // register commands

                var comsAttr = type.GetCustomAttribute <CommandsAttribute>();

                var comCount = 0;
                if (comsAttr != null && type.GetInterface(typeof(ICommandsDeclaringType).FullName) != null)
                {
                    comCount = ModuleCommandManager.RegisterCommandClass(context, type, false);
                }
                if (comCount > 0)
                {
                    typesCount++;
                }
                comTotCount += comCount;
            }

            // register module

            var descAttr    = assembly.GetCustomAttribute <AssemblyDescriptionAttribute>();
            var description = (descAttr != null) ? descAttr.Description : "";

            _modules.Add(
                modKey,
                moduleSpecification = new ModuleSpecification(
                    modKey,
                    Path.GetFileNameWithoutExtension(assembly.Location),
                    description,
                    assembly,
                    new ModuleInfo(
                        typesCount,
                        comTotCount,
                        hooksCount
                        )
                    ));

            // run module hook init
            ModuleHookManager.InvokeHooks(
                context,
                Hooks.ModuleInit,
                (o) =>
            {
                moduleSpecification.IsInitialized = true;
            }
                );

            return(moduleSpecification);
        }
Example #21
0
        /// <summary>
        /// search items in file system
        /// </summary>
        /// <param name="context"></param>
        /// <param name="path"></param>
        /// <param name="pattern"></param>
        /// <param name="top"></param>
        /// <param name="all"></param>
        /// <param name="dirs"></param>
        /// <param name="attributes"></param>
        /// <param name="shortPathes"></param>
        /// <param name="contains"></param>
        /// <param name="checkPatternOnFullName"></param>
        /// <param name="counts"></param>
        /// <param name="print"></param>
        /// <param name="alwaysSelectDirs"></param>
        /// <param name="ignoreCase"></param>
        /// <param name="printMatches"></param>
        /// <returns></returns>
        public static List <FileSystemPath> FindItems(
            CommandEvaluationContext context,
            string path,
            string pattern,
            bool top,
            bool all,
            bool dirs,
            bool attributes,
            bool shortPathes,
            string contains,
            bool checkPatternOnFullName,
            FindCounts counts,
            bool print,
            bool alwaysSelectDirs = false,
            bool ignoreCase       = false,
            bool printMatches     = false)
        {
            bool isFile = File.Exists(path);
            var  dinf   = isFile ? null : new DirectoryInfo(path);
            List <FileSystemPath> items = new List <FileSystemPath>();
            bool hasPattern             = !string.IsNullOrWhiteSpace(pattern);
            bool hasContains            = !string.IsNullOrWhiteSpace(contains);

            if (context.CommandLineProcessor.IsCancellationRequested)
            {
                return(items);
            }

            try
            {
                if (!isFile)
                {
                    counts.ScannedFoldersCount++;
                }
                var scan = isFile ? new FileSystemInfo[] { new FileInfo(path) }
                    : dinf.GetFileSystemInfos();

                foreach (var fsinf in scan)
                {
                    var sitem = FileSystemPath.Get(fsinf);

                    if (sitem.IsDirectory)
                    {
                        if ((dirs || all) && (alwaysSelectDirs || (!hasPattern || MatchWildcard(pattern, checkPatternOnFullName ? sitem.FileSystemInfo.FullName : sitem.FileSystemInfo.Name, ignoreCase))))
                        {
                            items.Add(sitem);
                            if (print)
                            {
                                sitem.Echo(new EchoEvaluationContext(context.Out, context, new FileSystemPathFormattingOptions(attributes, shortPathes, "", Br)));
                            }
                            counts.FoldersCount++;
                        }
                        else
                        {
                            sitem = null;
                        }

                        if (!top)
                        {
                            items.AddRange(FindItems(context, fsinf.FullName, pattern, top, all, dirs, attributes, shortPathes, contains, checkPatternOnFullName, counts, print, alwaysSelectDirs, ignoreCase, printMatches));
                        }
                    }
                    else
                    {
                        counts.ScannedFilesCount++;
                        if (!dirs && (!hasPattern || MatchWildcard(pattern, checkPatternOnFullName ? sitem.FileSystemInfo.FullName : sitem.FileSystemInfo.Name, ignoreCase)))
                        {
                            var matches = new List <string>();
                            if (hasContains)
                            {
                                try
                                {
                                    if (!FilePath.IsBinaryFile(sitem.FileSystemInfo.FullName))
                                    {
                                        // skip non text files
                                        var(lines, platform, eol) = TextFileReader.ReadAllLines(sitem.FileSystemInfo.FullName);
                                        bool match = false;
                                        for (int i = 0; i < lines.Length; i++)
                                        {
                                            if (lines[i].Contains(contains))
                                            {
                                                match |= true;
                                                if (printMatches)
                                                {
                                                    int j   = lines[i].IndexOf(contains);
                                                    var loc = $"\t{context.ShellEnv.Colors.MarginText} {$"line {i},col {j}".PadRight(24)} ";
                                                    var txt = lines[i].Replace(contains, context.ShellEnv.Colors.TextExtractSelectionBlock + contains + Rdc + context.ShellEnv.Colors.TextExtract);
                                                    matches.Add(loc + context.ShellEnv.Colors.TextExtract + txt + Rdc);
                                                }
                                            }
                                        }
                                        if (!match)
                                        {
                                            sitem = null;
                                        }
                                    }
                                    else
                                    {
                                        sitem = null;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    context.Errorln($"file read error: {ex.Message} when accessing file: {sitem.PrintableFullName}");
                                    sitem = null;
                                }
                            }
                            if (sitem != null)
                            {
                                counts.FilesCount++;
                                items.Add(sitem);
                                if (print && context.Out.IsModified && matches.Count > 0)
                                {
                                    context.Out.Echoln("");
                                }
                                if (print)
                                {
                                    sitem.Echo(new EchoEvaluationContext(context.Out, context, new FileSystemPathFormattingOptions(attributes, shortPathes, "", Br)));
                                }
                            }
                            if (matches.Count > 0)
                            {
                                matches.ForEach(x => context.Out.Echoln(x));
                            }
                            matches.Clear();
                        }
                        else
                        {
                            sitem = null;
                        }
                    }

                    if (context.CommandLineProcessor.IsCancellationRequested)
                    {
                        return(items);
                    }
                }
                return(items);
            }
            catch (UnauthorizedAccessException)
            {
                context.Errorln($"unauthorized access to {new DirectoryPath(path).PrintableFullName}");
                return(items);
            }
        }
Example #22
0
        public ModuleSpecification RegisterModule(
            CommandEvaluationContext context,
            Assembly assembly)
        {
            ModuleSpecification moduleSpecification = null;

            try
            {
                var moduleAttr = assembly.GetCustomAttribute <ShellModuleAttribute>();
                if (moduleAttr == null)
                {
                    context.Errorln($"assembly is not a shell module: '{assembly.FullName}'");
                    return(ModuleSpecification.ModuleSpecificationNotDefined);
                }

                // id is the name of the assembly (/!\ should not fit nuget packet id)

                var modKey = ModuleKey(assembly, out var id, out var ver);
                var assKey = AssemblyKey(assembly);
                if (_loadedModules.Contains(assKey))
                {
                    throw new Exception($"assembly already loaded: '{assKey}'");
                }

                if (_modules.ContainsKey(modKey))
                {
                    context.Errorln($"module already registered: {modKey} (path={assembly.FullName})");
                    return(ModuleSpecification.ModuleSpecificationNotDefined);
                }

                var typesCount  = 0;
                var comTotCount = 0;
                var hooksCount  = 0;

                foreach (var type in assembly.GetTypes())
                {
                    // register hooks

                    var hookAttr = type.GetCustomAttribute <HooksAttribute>();
                    if (hookAttr != null)
                    {
                        // module,class owns hooks
                        foreach (var mi in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                        {
                            var hook = mi.GetCustomAttribute <HookAttribute>();
                            if (hook != null)
                            {
                                ModuleHookManager.RegisterHook(context, hook.HookName, mi);
                                hooksCount++;
                            }
                        }
                    }

                    // register commands

                    var comsAttr = type.GetCustomAttribute <CommandsAttribute>();

                    var comCount = 0;
                    if (comsAttr != null && type.GetInterface(typeof(ICommandsDeclaringType).FullName) != null)
                    {
                        comCount = ModuleCommandManager.RegisterCommandClass(context, type, false);
                    }
                    if (comCount > 0)
                    {
                        typesCount++;
                    }
                    comTotCount += comCount;
                }

                // register module

                var descAttr    = assembly.GetCustomAttribute <AssemblyDescriptionAttribute>();
                var description = (descAttr != null) ? descAttr.Description : "";
                _modules.Add(
                    modKey,
                    moduleSpecification = new ModuleSpecification(
                        modKey,
                        Path.GetFileNameWithoutExtension(assembly.Location),
                        description,
                        assembly,
                        new ModuleInfo(
                            typesCount,
                            comTotCount,
                            hooksCount
                            )
                        ));
                _loadedModules.Add(AssemblyKey(assembly));
                _loadedAssemblies.Add(assembly.Location.ToLower(), assembly);

                // run module hook init
                ModuleHookManager.InvokeHooks(
                    context,
                    Hooks.ModuleInit,
                    HookTriggerMode.FirstTimeOnly,
                    (o) =>
                {
                    moduleSpecification.IsInitialized = true;
                }
                    );
            }
            catch (Exception ex)
            {
                throw new Exception($"register module assembly '{assembly.FullName}' failed due to error: '{ex.Message}'", ex);
            }

            return(moduleSpecification);
        }
        public CommandVoidResult History(
            CommandEvaluationContext context,
            [Option("i", "invoke", "invoke the command at the entry number in the history list", true, true)] int num,
            [Option("c", "clear", "clear the loaded history list")] bool clear,
            [Option("w", "write", "write history lines to the history file (content of the file is replaced)")]
            [OptionRequireParameter("file")]  bool writeToFile,
            [Option("a", "append", "append history lines to the history file")]
            [OptionRequireParameter("file")]  bool appendToFile,
            [Option("r", "read", "read the history file and append the content to the history list")]
            [OptionRequireParameter("file")]  bool readFromFile,
            [Option("d", "read-diff", "read the history file and append the content not already in the history list to the history list")]
            [OptionRequireParameter("file")] bool appendFromFile,
            [Parameter(1, "file", true)] FilePath file
            )
        {
            var hist = context.CommandLineProcessor.CmdsHistory.History;
            var max  = hist.Count().ToString().Length;
            int i    = 1;
            var f    = DefaultForegroundCmd;

            if (num > 0)
            {
                if (num < 1 || num > hist.Count)
                {
                    context.Errorln($"history entry number out of range (1..{hist.Count})");
                    return(new CommandVoidResult(ReturnCode.Error));
                }
                var h = hist[num - 1];
                context.CommandLineProcessor.CommandLineReader.SendNextInput(h);
                return(new CommandVoidResult());
            }

            if (clear)
            {
                context.CommandLineProcessor.CmdsHistory.ClearHistory();
                return(new CommandVoidResult());
            }

            if (appendToFile || readFromFile || appendFromFile || writeToFile)
            {
                file ??= context.CommandLineProcessor.CmdsHistory.FilePath;
                if (file.CheckPathExists(context))
                {
                    if (writeToFile)
                    {
                        File.Delete(context.CommandLineProcessor.CmdsHistory.FilePath.FullName);
                        File.AppendAllLines(file.FullName, hist);
                    }
                    if (appendToFile)
                    {
                        File.AppendAllLines(file.FullName, hist);
                    }
                    if (readFromFile)
                    {
                        var lines = File.ReadAllLines(file.FullName);
                        foreach (var line in lines)
                        {
                            context.CommandLineProcessor.CmdsHistory.HistoryAppend(line);
                        }
                        context.CommandLineProcessor.CmdsHistory.HistorySetIndex(-1, false);
                    }
                    if (appendFromFile)
                    {
                        var lines = File.ReadAllLines(file.FullName);
                        foreach (var line in lines)
                        {
                            if (!context.CommandLineProcessor.CmdsHistory.HistoryContains(line))
                            {
                                context.CommandLineProcessor.CmdsHistory.HistoryAppend(line);
                            }
                        }
                        context.CommandLineProcessor.CmdsHistory.HistorySetIndex(-1, false);
                    }
                }
                return(new CommandVoidResult());
            }

            foreach (var h in hist)
            {
                if (context.CommandLineProcessor.CancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }
                var hp = $"  {context.ShellEnv.Colors.Numeric}{i.ToString().PadRight(max + 2, ' ')}{f}";
                context.Out.Echo(hp);
                context.Out.ConsolePrint(h, true);
                i++;
            }
            return(new CommandVoidResult());
        }
        public CommandVoidResult Help(
            CommandEvaluationContext context,
            [Option("s", "short", "short display: decrase output details")] bool shortView,
            [Option("v", "verbose", "set verbose view: increase output details")] bool verboseView,
            [Option("a", "all", "list all commands")] bool all,
            [Option("n", "namespace", "filter commands list by namespace value or wildcard or regex (wildcard have ?,* , regex starts with \\)", true, true)] PatternString @namespace,
            [Option("t", "type", "filter commands list on command declaring type name value or wildcard or regex", true, true)] PatternString type,
            [Option("m", "module", "filter commands list by module name value or wildcard or regex ", true, true)] PatternString module,
            [Option("l", "list", "if one of -n|-t|-m is set, output list of filtered values")] bool listFilter,
            [Parameter("output help for the command having the name 'commandName'", true)] string commandName
            )
        {
            var hascn      = !string.IsNullOrWhiteSpace(commandName);
            var list       = !all && !hascn;
            var cmds       = context.CommandLineProcessor.ModuleManager.ModuleCommandManager.AllCommands.AsQueryable();
            var namespaces = cmds.Select(x => x.Namespace).Distinct().ToList();

            namespaces.Sort();
            bool ignoreCase = true;

            if (hascn)
            {
                cmds = cmds.Where(x => x.Name.Equals(commandName, CommandLineParser.SyntaxMatchingRule));
            }

            if (cmds.Count() > 0)
            {
                #region filter on declaring type

                if (!string.IsNullOrWhiteSpace(type))
                {
                    var typenames = context.CommandLineProcessor.ModuleManager.ModuleCommandManager.CommandDeclaringTypesAssemblyQualifiedNames.ToList();
                    var typelst   = typenames
                                    .Select(x => Type.GetType(x))
                                    .Where(x => type.Match(x.Name))
                                    .ToList();
                    typelst.Sort((x, y) => x.Name.CompareTo(y.Name));
                    shortView = !verboseView;

                    if (!listFilter)
                    {
                        cmds = cmds.Where(x => type.Match(x.DeclaringTypeShortName, ignoreCase));
                    }
                    else
                    {
                        var sfx = "Commands";
                        string TypeName(Type type)
                        {
                            var s = shortView ? type.Name : type.FullName;

                            if (shortView && s.EndsWith(sfx))
                            {
                                s = s.Substring(0, s.Length - sfx.Length);
                            }
                            return(s);
                        }

                        if (typelst.Count > 0)
                        {
                            var maxtl = typelst.Select(x => TypeName(x).Length).Max();

                            foreach (var typ in typelst)
                            {
                                var cmdattr = typ.GetCustomAttribute <CommandsAttribute>();
                                context.Out.Echoln(Darkcyan + TypeName(typ).PadRight(maxtl) + Tab + DefaultForegroundCmd + cmdattr.Description);
                            }
                        }
                        return(new CommandVoidResult());
                    }
                }

                #endregion

                #region filter on module

                if (cmds.Count() > 0 && !string.IsNullOrWhiteSpace(module))
                {
                    var mods     = context.CommandLineProcessor.ModuleManager.Modules;
                    var modnames = mods.Values.Where(x => module.Match(x.Name)).Select(x => x.Name).ToList();
                    modnames.Sort();
                    shortView = !verboseView;

                    if (!listFilter)
                    {
                        cmds = cmds.Where(x => module.Match(x.ModuleName, ignoreCase));
                    }
                    else
                    {
                        if (modnames.Count > 0)
                        {
                            var maxml = modnames.Select(x => x.Length).Max();
                            foreach (var modname in modnames)
                            {
                                context.Out.Echoln(Darkcyan + modname.PadRight(maxml) + Tab + DefaultForegroundCmd + mods[modname].Description);
                            }
                        }
                        return(new CommandVoidResult());
                    }
                }

                #endregion

                #region filter on namespace

                if (cmds.Count() > 0 && !string.IsNullOrWhiteSpace(@namespace))
                {
                    var nslst = namespaces.Where(x => @namespace.Match(x));
                    shortView = !verboseView;

                    if (!listFilter)
                    {
                        cmds = cmds.Where(x => @namespace.Match(x.Namespace, ignoreCase));
                    }
                    else
                    {
                        foreach (var ns in nslst)
                        {
                            context.Out.Echoln(Darkcyan + ns);
                        }
                        return(new CommandVoidResult());
                    }
                }

                #endregion

                var ncmds = cmds.ToList();
                ncmds.Sort(new Comparison <CommandSpecification>((x, y) => x.Name.CompareTo(y.Name)));
                cmds = ncmds.AsQueryable();
                if (cmds.Count() > 0)
                {
                    var maxcmdlength     = cmds.Select(x => x.Name.Length).Max() + 1;
                    var maxcmdtypelength = cmds.Select(x => x.DeclaringTypeShortName.Length).Max() + 1;
                    var maxmodlength     = cmds.Select(x => Path.GetFileNameWithoutExtension(x.MethodInfo.DeclaringType.Assembly.Location).Length).Max() + 1;
                    var maxnslength      = cmds.Select(x => x.Namespace.Length).Max() + 1;

                    if (list)
                    {
                        shortView = !verboseView;
                    }

                    var groupByNs = list;
                    if (groupByNs)
                    {
                        // get all fs
                        var cmdByNs = cmds.GroupBy((x) => x.Namespace).ToList(); // ordered
                        cmdByNs.Sort((x, y) => x.Key.CompareTo(y.Key));
                        int g = 0;
                        foreach (var grouping in cmdByNs)
                        {
                            if (grouping.Count() > 0)
                            {
                                if (g > 0)
                                {
                                    context.Out.Echoln();
                                }
                                context.Out.Echoln($"{ANSI.SGR_Underline}{context.ShellEnv.Colors.Label}{grouping.Key}{ANSI.SGR_UnderlineOff}{context.ShellEnv.Colors.Default}{ANSI.CRLF}");
                                foreach (var item in grouping)
                                {
                                    _PrintCommandHelp(context, item, shortView, verboseView, list, maxnslength, maxcmdlength, maxcmdtypelength, maxmodlength, !string.IsNullOrWhiteSpace(commandName));
                                }
                                g++;
                            }
                        }
                    }
                    else
                    {
                        int n = 0;
                        foreach (var cmd in cmds)
                        {
                            if (!list && n > 0)
                            {
                                context.Out.Echoln();
                            }
                            _PrintCommandHelp(context, cmd, shortView, verboseView, list, maxnslength, maxcmdlength, maxcmdtypelength, maxmodlength, !string.IsNullOrWhiteSpace(commandName));
                            n++;
                        }
                    }
                }
            }
            else
            {
                context.Errorln($"Command not found: '{commandName}'");
                return(new CommandVoidResult(ReturnCode.Error));
            }
            return(new CommandVoidResult());
        }
        public CommandResult <QueryResultRoot> NugetQuery(
            CommandEvaluationContext context,
            [Parameter("the search terms to used to filter packages", true)] string query,
            [Option("s", "skip", "the number of results to skip, for pagination", true, true)] int skip   = -1,
            [Option("t", "take", "the number of results to return, for pagination", true, true)] int take = -1,
            [Option("r", "pre-release", "true or false determining whether to include pre-release packages (default no)")] bool preRelease = false,
            [Option("l", "sem-ver-level", "a SemVer 1.0.0 version string", true, true)] string semVerLevel = "2.0.0",
            [Option("p", "package-type", "the package type to use to filter packages (added in SearchQueryService/3.5.0)", true, true)] string packageType = null,
            [Option("u", "query-url", "nuget server api query service template url", true, true)] string url = QueryUrl
            )
        {
            QueryResultRoot @return = null;

            query ??= "";
            var queryString = url.Replace("{QUERY}", query.Trim());

            if (skip > -1)
            {
                queryString = queryString.Replace("{SKIP}", skip + "");
            }
            if (take > -1)
            {
                queryString = queryString.Replace("{TAKE}", take + "");
            }
            queryString = queryString.Replace("{PRERELEASE}", preRelease.ToString().ToLower());
            if (semVerLevel != null)
            {
                queryString = queryString.Replace("{SEMVERLEVEL}", semVerLevel);
            }
            if (packageType != null)
            {
                queryString = queryString.Replace("{PACKAGETYPE}", packageType);
            }
            queryString = queryString
                          .Replace("&skip={SKIP}", "")
                          .Replace("&take={TAKE}", "")
                          .Replace("&prerelease={PRERELEASE}", "")
                          .Replace("&semVerLevel={SEMVERLEVEL}", "")
                          .Replace("&packageType={PACKAGETYPE}", "");

            context.Out.Echo(context.ShellEnv.Colors.Log + $"GET {queryString} ... ");

            using var httpClient = new HttpClient();
            using var request    = new HttpRequestMessage(new HttpMethod("GET"), queryString);

            var tsk    = httpClient.SendAsync(request);
            var result = tsk.Result;

            if (result.IsSuccessStatusCode)
            {
                var res = result.Content.ReadAsStringAsync().Result;

                context.Out.Echoln(" Done(rdc)");
                context.Out.Echo(ANSI.RSTXTA + ANSI.CPL(1) + ANSI.EL(ANSI.ELParameter.p2));     // TODO: add as ANSI combo

                var obj = JsonConvert.DeserializeObject <QueryResultRoot>(res);
                @return = obj;

                if (obj != null && obj.Data != null)
                {
                    obj.Echo(new EchoEvaluationContext(context.Out, context));
                }
                else
                {
                    context.Errorln("invalid json");
                }
            }
            else
            {
                context.Errorln($"can't get response content: {result.ReasonPhrase}");
            }


            return(new CommandResult <QueryResultRoot>(@return));
        }
        public CommandResult <string> NugetPush(
            CommandEvaluationContext context,
            [Parameter(0, "package (.nuget) file path")] FilePath pkgFile,
            [Parameter(1, "target server api key")] string apiKey,
            [Option("u", "push-url", "nuget server api push service url", true, true)] string url = PushUrl,
            [Option("p", "protocol-version", "nuget thir party client protocol version", true, true)] string protocolVersion = ProtocolVersion
            )
        {
            var @return = "";

            if (pkgFile.CheckExists(context))
            {
                var ext   = Path.GetExtension(pkgFile.FullName);
                var atExt = ".nupkg";
                if (ext.ToLower() != atExt)
                {
                    context.Errorln($"bad file extension: '{ext}', should be '{atExt}'");
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(apiKey))
                    {
                        context.Errorln($"api key is required and can't be empty");
                    }
                    else
                    {
                        using var httpClient = new HttpClient();
                        using var request    = new HttpRequestMessage(new HttpMethod("PUT"), url);

                        request.Headers.Add("X-NuGet-ApiKey", apiKey);
                        request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
                        request.Headers.Add("X-NuGet-Protocol-Version", protocolVersion);
                        //request.Headers.Add("X-NuGet-Client-Version", "5.8.1");
                        //request.Headers.Add("user-agent", "NuGet Command Line / 5.8.1 (Microsoft Windows NT 10.0.19042.0)");

                        var content = new MultipartFormDataContent();

                        var fileContent = new ByteArrayContent(File.ReadAllBytes(pkgFile.FullName));

                        fileContent.Headers.ContentDisposition =
                            new ContentDispositionHeaderValue(
                                "form-data"
                                )
                        {
                            FileName = "package.nupkg"
                        };

                        fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

                        content.Add(fileContent);
                        request.Content = content;


                        context.Out.Echo(context.ShellEnv.Colors.Log + $"PUT {PushUrl} ... ");

                        var tsk = httpClient.SendAsync(request);

                        var result = tsk.Result;
                        if (result.IsSuccessStatusCode)
                        {
                            var res = result.Content.ReadAsStringAsync().Result;

                            context.Out.Echoln(" Done(rdc)");
                            context.Out.Echo(ANSI.RSTXTA + ANSI.CPL(1) + ANSI.EL(ANSI.ELParameter.p2));     // TODO: add as ANSI combo

                            @return = res;

                            if (res != null)
                            {
                                if (!string.IsNullOrWhiteSpace(res))
                                {
                                    context.Out.Echoln(res);
                                }
                            }
                            else
                            {
                                context.Warningln("quey result is empty");
                            }
                            context.Warningln("quey result is empty");

                            if (result.StatusCode == HttpStatusCode.Created ||
                                result.StatusCode == HttpStatusCode.Accepted)
                            {
                                context.Out.Echoln($"package '{Path.GetFileName(pkgFile.FullName)}' has been successfully pushed");
                            }
                        }
                        else
                        {
                            context.Errorln($"can't get response content: {(int)result.StatusCode} {result.ReasonPhrase}");
                        }
                    }
                }
            }
            return(new CommandResult <string>(@return));
        }
Example #27
0
        public int RegisterCommandClass(
            CommandEvaluationContext context,
            Type type,
            bool registerAsModule
            )
        {
            if (type.GetInterface(typeof(ICommandsDeclaringType).FullName) == null)
            {
                throw new Exception($"the type '{type.FullName}' must implements interface '{typeof(ICommandsDeclaringType).FullName}' to be registered as a command class");
            }

            var dtNamespaceAttr = type.GetCustomAttribute <CommandsNamespaceAttribute>();
            var dtNamespace     = (dtNamespaceAttr == null) ? "" : CheckAndNormalizeCommandNamespace(dtNamespaceAttr.Segments);

            var    comsCount = 0;
            object instance  = Activator.CreateInstance(type, new object[] { });
            var    methods   = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            if (registerAsModule && _modules.ContainsKey(type.FullName))
            {
                context.Errorln($"a module with same name than the commands declaring type '{type.FullName}' is already registered");
                return(0);
            }

            foreach (var method in methods)
            {
                var cmd = method.GetCustomAttribute <CommandAttribute>();
                if (cmd != null)
                {
                    if (!method.ReturnType.HasInterface(typeof(ICommandResult)))
                    {
                        context.Errorln($"class={type.FullName} method={method.Name} wrong return type. should be of type '{typeof(ICommandResult).FullName}', but is of type: {method.ReturnType.FullName}");
                    }
                    else
                    {
                        // ⏺ build the command specification from the method meta-data

                        var cmdNamespaceAttr  = method.GetCustomAttribute <CommandNamespaceAttribute>();
                        var cmdNamespace      = cmdNamespaceAttr == null ? dtNamespace : CheckAndNormalizeCommandNamespace(cmdNamespaceAttr.Segments);
                        var cmdAliasesAttrLst = method.GetCustomAttributes <CommandAliasAttribute>();
                        var cmdAliases        = cmdAliasesAttrLst?.Select(x => (x.AliasName, x.AliasText)).ToList();
                        if (cmdAliases.Count == 0)
                        {
                            cmdAliases = null;                        // convention
                        }
                        #region init from method parameters attributes

                        var  paramspecs  = new List <CommandParameterSpecification>();
                        bool syntaxError = false;
                        var  pindex      = 0;
                        foreach (var parameter in method.GetParameters())
                        {
                            if (pindex == 0)
                            {
                                // manadatory: param 0 is CommandEvaluationContext
                                if (parameter.ParameterType != typeof(CommandEvaluationContext))
                                {
                                    context.Errorln($"class={type.FullName} method={method.Name} parameter 0 ('{parameter.Name}') should be of type '{typeof(CommandEvaluationContext).FullName}', but is of type: {parameter.ParameterType.FullName}");
                                    syntaxError = true;
                                    break;
                                }
                            }
                            else
                            {
                                CommandParameterSpecification pspec = null;
                                object defval = null;
                                if (!parameter.HasDefaultValue && parameter.ParameterType.IsValueType)
                                {
                                    defval = Activator.CreateInstance(parameter.ParameterType);
                                }

                                // param
                                var paramAttr = parameter.GetCustomAttribute <ParameterAttribute>();
                                if (paramAttr != null)
                                {
                                    // TODO: validate command specification (eg. indexs validity)
                                    pspec = new CommandParameterSpecification(
                                        parameter.Name,
                                        paramAttr.Description,
                                        paramAttr.IsOptional,
                                        paramAttr.Index,
                                        null,
                                        null,
                                        true,
                                        parameter.HasDefaultValue,
                                        paramAttr.HasDefaultValue ?
                                        paramAttr.DefaultValue
                                            : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval),
                                        parameter);
                                }

                                // option
                                var optAttr = parameter.GetCustomAttribute <OptionAttribute>();
                                if (optAttr != null)
                                {
                                    var reqParamAttr = parameter.GetCustomAttribute <OptionRequireParameterAttribute>();
                                    try
                                    {
                                        pspec = new CommandParameterSpecification(
                                            parameter.Name,
                                            optAttr.Description,
                                            optAttr.IsOptional,
                                            -1,
                                            optAttr.OptionName /*?? parameter.Name*/,
                                            optAttr.OptionLongName,
                                            optAttr.HasValue,
                                            parameter.HasDefaultValue,
                                            optAttr.HasDefaultValue ?
                                            optAttr.DefaultValue
                                                : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval),
                                            parameter,
                                            reqParamAttr?.RequiredParameterName);
                                    }
                                    catch (Exception ex)
                                    {
                                        context.Errorln(ex.Message);
                                    }
                                }

                                if (pspec == null)
                                {
                                    syntaxError = true;
                                    context.Errorln($"invalid parameter: class={type.FullName} method={method.Name} name={parameter.Name}");
                                }
                                else
                                {
                                    paramspecs.Add(pspec);
                                }
                            }
                            pindex++;
                        }

                        #endregion

                        if (!syntaxError)
                        {
                            var cmdNameAttr = method.GetCustomAttribute <CommandNameAttribute>();

                            var cmdName = CheckAndNormalizeCommandName(
                                (cmdNameAttr != null && cmdNameAttr.Name != null) ?
                                cmdNameAttr.Name
                                        : (cmd.Name ?? method.Name));

                            bool registered = true;
                            CommandSpecification cmdspec = null;

                            try
                            {
                                cmdspec = new CommandSpecification(
                                    cmdNamespace,
                                    cmdName,
                                    cmd.Description,
                                    cmd.LongDescription,
                                    cmd.Documentation,
                                    method,
                                    instance,
                                    cmdAliases,
                                    paramspecs);
                            } catch (Exception ex)
                            {
                                context.Errorln($"error in command '{cmdName}' specification: {ex.Message}");
                            }

                            if (cmdspec != null)
                            {
                                if (_commands.TryGetValue(cmdspec.Name, out var cmdlst))
                                {
                                    if (cmdlst.Select(x => x.MethodInfo.DeclaringType == type).Any())
                                    {
                                        context.Errorln($"command already registered: '{cmdspec.Name}' in type '{cmdspec.DeclaringTypeFullName}'");
                                        registered = false;
                                    }
                                    else
                                    {
                                        cmdlst.Add(cmdspec);
                                    }
                                }
                                else
                                {
                                    _commands.Add(cmdspec.Name, new List <CommandSpecification> {
                                        cmdspec
                                    });
                                }


                                if (registered)
                                {
                                    _syntaxAnalyzer.Add(cmdspec);
                                    comsCount++;
                                    // register command Aliases
                                    if (cmdspec.Aliases != null)
                                    {
                                        foreach (var alias in cmdspec.Aliases)
                                        {
                                            context.CommandLineProcessor.CommandsAlias.AddOrReplaceAlias(
                                                context,
                                                alias.name,
                                                alias.text
                                                );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (registerAsModule)
            {
                if (comsCount == 0)
                {
                    context.Errorln($"no commands found in type '{type.FullName}'");
                }
                else
                {
                    var descAttr    = type.GetCustomAttribute <CommandsAttribute>();
                    var description = descAttr != null ? descAttr.Description : "";
                    _modules.Add(
                        type.FullName,      // key not from assembly but from type
                        new ModuleSpecification(
                            type.FullName,
                            ModuleUtil.DeclaringTypeShortName(type),
                            description,
                            type.Assembly,
                            new ModuleInfo(
                                1,
                                comsCount
                                ),
                            type
                            ));
                }
            }
            return(comsCount);
        }
 public CommandResult <(List <(FileSystemPath source, FileSystemPath target)> items, FindCounts counts)> Mv(
     CommandEvaluationContext context,
     [Parameter("source: file/directory or several corresponding to a wildcarded path")] WildcardFilePath source,
     [Parameter(1, "target: a file or a directory")] FileSystemPath target,
     [Option("i", "interactive", "prompt before overwrite")] bool interactive,
     [Option("v", "verbose", "explain what is being done, but actually does nothing")] bool verbose
     )
 {
     if (source.CheckExists(context))
     {
         var counts      = new FindCounts();
         var items       = FindItems(context, source.FullName, source.WildCardFileName ?? "*", true, true, false, true, false, null, false, counts, false, false);
         var sourceCount = items.Count;
         List <(FileSystemPath src, FileSystemPath tgt)> r = new List <(FileSystemPath src, FileSystemPath tgt)>();
         if (sourceCount > 1)
         {
             if (target.CheckExists(context))
             {
                 if (!target.IsDirectory)
                 {
                     context.Errorln("target must be a directory");
                     return(new CommandResult <(List <(FileSystemPath, FileSystemPath)> items, FindCounts counts)>(
                                (new List <(FileSystemPath, FileSystemPath)> {
                         (source, target)
                     }, counts), ReturnCode.Error
                                ));
                 }
                 else
                 {
                     // move multiple source to dest
                     foreach (var item in items)
                     {
                         var msg = $"move {item.GetPrintableName()} to {target.GetPrintableName()}";
                         if (!interactive || Confirm("mv: " + msg))
                         {
                             if (source.IsFile)
                             {
                                 var newdest = Path.Combine(target.FullName, item.Name);
                                 r.Add((item, new FileSystemPath(newdest)));
                                 File.Move(item.FullName, newdest);
                             }
                             else
                             {
                                 var newdest = Path.Combine(target.FullName, item.Name);
                                 Directory.Move(item.FullName, newdest);
                                 r.Add((item, new DirectoryPath(newdest)));
                             }
                             if (verbose)
                             {
                                 context.Out.Echoln(msg.Replace("move ", "moved "));
                             }
                         }
                     }
                 }
             }
         }
         else
         {
             if (target.CheckExists(context))
             {
                 if (target.IsDirectory)
                 {
                     // move one source to dest
                     var msg = $"move {source.GetPrintableNameWithWlidCard()} to {target.GetPrintableName()}";
                     if (!interactive || Confirm("mv: " + msg))
                     {
                         if (source.IsFile)
                         {
                             var newdest = Path.Combine(target.FullName, source.NameWithWildcard);
                             File.Move(source.FullNameWithWildcard, newdest);
                             r.Add((new FilePath(source.FullNameWithWildcard), new FilePath(newdest)));
                         }
                         else
                         {
                             var newdest = Path.Combine(target.FullName, source.NameWithWildcard);
                             Directory.Move(source.FullName, newdest);
                             r.Add((source, new DirectoryPath(newdest)));
                         }
                         if (verbose)
                         {
                             context.Out.Echoln(msg.Replace("move ", "moved "));
                         }
                     }
                 }
                 else
                 {
                     // rename source (file) to dest (overwrite dest)
                     var msg = $"rename {source.GetPrintableNameWithWlidCard()} to {target.GetPrintableName()}";
                     if (!interactive || Confirm("mv: " + msg))
                     {
                         target.FileSystemInfo.Delete();
                         File.Move(source.FullNameWithWildcard, target.FullName);
                         r.Add((new FilePath(source.FullNameWithWildcard), target));
                         if (verbose)
                         {
                             context.Out.Echoln(msg.Replace("rename ", "renamed "));
                         }
                     }
                 }
             }
             else
             {
                 // rename source to dest
                 var msg = $"rename {source.GetPrintableNameWithWlidCard()} to {target.GetPrintableName()}";
                 if (!interactive || Confirm("mv: " + msg))
                 {
                     if (source.IsFile)
                     {
                         File.Move(source.FullNameWithWildcard, target.FullName);
                         r.Add((new FilePath(source.FullNameWithWildcard), target));
                     }
                     else
                     {
                         Directory.Move(source.FullName, target.FullName);
                         r.Add((source, target));
                     }
                     if (verbose)
                     {
                         context.Out.Echoln(msg.Replace("rename ", "renamed "));
                     }
                 }
             }
         }
         return(new CommandResult <(List <(FileSystemPath source, FileSystemPath target)> items, FindCounts counts)>
                    ((r, counts)));
     }
     else
     {
         return(new CommandResult <(List <(FileSystemPath, FileSystemPath)> items, FindCounts counts)>
                    ((new List <(FileSystemPath, FileSystemPath)> {
             (source, null)
         }, new FindCounts())));
     }
 }