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())); }
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)); } }
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)); }
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"); } }
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); }
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); }
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)); }
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); } } }
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)); }
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); } }
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 + ""); } }
CommandResult <List <ModuleSpecification> > _ModuleErr(CommandEvaluationContext context, string reason) { context?.Errorln(reason); return(new CommandResult <List <ModuleSpecification> >(ReturnCode.Error, reason)); }
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); }
/// <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); } }
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)); }
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()))); } }