private List <CkanModule> GetAllMods(ConsoleTheme theme, bool force = false) { ScanForMods(); if (allMods == null || force) { if (!registry?.HasAnyAvailable() ?? false) { UpdateRegistry(theme, false); } allMods = new List <CkanModule>(registry.CompatibleModules(manager.CurrentInstance.VersionCriteria())); foreach (InstalledModule im in registry.InstalledModules) { CkanModule m = null; try { m = registry.LatestAvailable(im.identifier, manager.CurrentInstance.VersionCriteria()); } catch (ModuleNotFoundKraken) { } if (m == null) { // Add unavailable installed mods to the list allMods.Add(im.Module); } } } return(allMods); }
public MessageTemplateOutputTokenRenderer(ConsoleTheme theme, PropertyToken token, IFormatProvider formatProvider) { _theme = theme ?? throw new ArgumentNullException(nameof(theme)); _token = token ?? throw new ArgumentNullException(nameof(token)); bool isLiteral = false, isJson = false; if (token.Format != null) { for (var i = 0; i < token.Format.Length; ++i) { if (token.Format[i] == 'l') { isLiteral = true; } else if (token.Format[i] == 'j') { isJson = true; } } } var valueFormatter = isJson ? (ThemedValueFormatter) new ThemedJsonValueFormatter(theme, formatProvider) : new ThemedDisplayValueFormatter(theme, formatProvider); _renderer = new ThemedMessageTemplateRenderer(theme, valueFormatter, isLiteral); }
public ThemedMessageTemplateRenderer(ConsoleTheme theme, ThemedValueFormatter valueFormatter, bool isLiteral) { _theme = theme ?? throw new ArgumentNullException(nameof(theme)); _valueFormatter = valueFormatter; _isLiteral = isLiteral; _unthemedValueFormatter = valueFormatter.SwitchTheme(NoTheme); }
private void Download(ConsoleTheme theme) { ProgressScreen ps = new ProgressScreen($"Downloading {mod.identifier}"); NetAsyncModulesDownloader dl = new NetAsyncModulesDownloader(ps, manager.Cache); ModuleInstaller inst = ModuleInstaller.GetInstance(manager.CurrentInstance, manager.Cache, ps); LaunchSubScreen( theme, ps, (ConsoleTheme th) => { try { dl.DownloadModules(new List <CkanModule> { mod }); if (!manager.Cache.IsMaybeCachedZip(mod)) { ps.RaiseError("Download failed, file is corrupted"); } } catch (Exception ex) { ps.RaiseError($"Download failed: {ex}"); } } ); // Don't let the installer re-use old screen references inst.User = null; }
/// <summary> /// Writes log events to <see cref="System.Console"/>. /// </summary> /// <param name="sinkConfiguration">Logger sink configuration.</param> /// <param name="restrictedToMinimumLevel">The minimum level for /// events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.</param> /// <param name="levelSwitch">A switch allowing the pass-through minimum level /// to be changed at runtime.</param> /// <param name="outputTemplate">A message template describing the format used to write to the sink. /// the default is <code>"[{Timestamp:HH:mm:ss} {Level:u3}] {Message}{NewLine}{Exception}"</code>.</param> /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param> /// <param name="standardErrorFromLevel">Specifies the level at which events will be written to standard error.</param> /// <param name="theme">The theme to apply to the styled output. If not specified, /// uses <see cref="SystemConsoleTheme.Literate"/>.</param> /// <returns>Configuration object allowing method chaining.</returns> public static LoggerConfiguration Console( this LoggerSinkConfiguration sinkConfiguration, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, string outputTemplate = DefaultConsoleOutputTemplate, IFormatProvider formatProvider = null, LoggingLevelSwitch levelSwitch = null, LogEventLevel?standardErrorFromLevel = null, ConsoleTheme theme = null) { if (sinkConfiguration == null) { throw new ArgumentNullException(nameof(sinkConfiguration)); } if (outputTemplate == null) { throw new ArgumentNullException(nameof(outputTemplate)); } var appliedTheme = System.Console.IsOutputRedirected || System.Console.IsErrorRedirected ? ConsoleTheme.None : theme ?? SystemConsoleThemes.Literate; var formatter = new OutputTemplateRenderer(appliedTheme, outputTemplate, formatProvider); return(sinkConfiguration.Sink(new ConsoleSink(appliedTheme, formatter, standardErrorFromLevel), restrictedToMinimumLevel, levelSwitch)); }
public static LoggerConfiguration DummyConsole( this LoggerSinkConfiguration loggerSinkConfiguration, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, ConsoleTheme theme = null) { return(loggerSinkConfiguration.Sink(new DummyConsoleSink(theme), restrictedToMinimumLevel)); }
private void drawLine(ConsoleTheme theme, int y, FancyLinePiece[] pieces) { // First we need to know how long the text is for centering int textLen = 0; foreach (FancyLinePiece p in pieces) { textLen += p.Text.Length; } int boxW = Console.WindowWidth - 2 * horizMargin; int leftPad = (boxW - textLen) / 2; if (leftPad < 0) { leftPad = 0; } int rightPad = boxW - textLen - leftPad; if (rightPad < 0) { rightPad = 0; } // Left padding Console.SetCursorPosition(horizMargin, y); Console.BackgroundColor = theme.ExitInnerBg; Console.Write(new string(' ', leftPad)); foreach (FancyLinePiece p in pieces) { p.Draw(); } Console.Write(new string(' ', rightPad)); }
/// <summary> /// Try to load the registry of an instance /// </summary> /// <param name="theme">The visual theme to use to draw the dialog</param> /// <param name="ksp">Game instance</param> /// <param name="render">Function that shows a loading message</param> /// <returns> /// True if successfully loaded, false if it's locked or the registry was corrupted, etc. /// </returns> public static bool TryGetInstance(ConsoleTheme theme, GameInstance ksp, Action <ConsoleTheme> render) { bool retry; do { try { retry = false; // Show loading message render(theme); // Try to get the lock; this will throw if another instance is in there RegistryManager.Instance(ksp); } catch (RegistryInUseKraken k) { ConsoleMessageDialog md = new ConsoleMessageDialog( $"Lock file with live process ID found at {k.lockfilePath}\n\n" + "This means that another instance of CKAN probably is accessing this instance." + " You can delete the file to continue, but data corruption is very likely.\n\n" + "Do you want to delete this lock file to force access?", new List <string>() { "Cancel", "Force" } ); if (md.Run(theme) == 1) { // Delete it File.Delete(k.lockfilePath); retry = true; } else { // User cancelled, return failure return(false); } } catch (NotKSPDirKraken k) { ConsoleMessageDialog errd = new ConsoleMessageDialog( $"Error loading {ksp.GameDir()}:\n{k.Message}", new List <string>() { "OK" } ); errd.Run(theme); return(false); } catch (Exception e) { ConsoleMessageDialog errd = new ConsoleMessageDialog( $"Error loading {Path.Combine(ksp.CkanDir(), "registry.json")}:\n{e.Message}", new List <string>() { "OK" } ); errd.Run(theme); return(false); } } while (retry); // If we got the lock, then return success return(true); }
public static void WriteCsv(IEnumerable <Token <CsvToken> > csv, ConsoleTheme theme, TextWriter output, bool hasHeaderRow) { var isHeaderRow = hasHeaderRow; foreach (var token in csv) { switch (token.Kind) { case CsvToken.Newline: output.WriteLine(); isHeaderRow = false; break; case CsvToken.Comma: theme.Set(output, ConsoleThemeStyle.TertiaryText); output.Write(','); theme.Reset(output); break; case CsvToken.DoubleQuote: theme.Set(output, ConsoleThemeStyle.TertiaryText); output.Write('"'); theme.Reset(output); break; case CsvToken.Boolean: theme.Set(output, ConsoleThemeStyle.Boolean); output.Write(token.ToStringValue()); theme.Reset(output); break; case CsvToken.Null: theme.Set(output, ConsoleThemeStyle.Null); output.Write(token.ToStringValue()); theme.Reset(output); break; case CsvToken.Number: theme.Set(output, ConsoleThemeStyle.Number); output.Write(token.ToStringValue()); theme.Reset(output); break; case CsvToken.EscapedDoubleQuote: theme.Set(output, ConsoleThemeStyle.Scalar); output.Write(token.ToStringValue()); theme.Reset(output); break; case CsvToken.Text: theme.Set(output, isHeaderRow ? ConsoleThemeStyle.Name : ConsoleThemeStyle.Text); output.Write(token.ToStringValue()); theme.Reset(output); break; default: throw new ArgumentException($"Unrecognized token `{token}`."); } } }
private bool SelectInstall(ConsoleTheme theme) { GameInstance prevInst = manager.CurrentInstance; var prevRepos = new SortedDictionary <string, Repository>(registry.Repositories); var prevVerCrit = prevInst.VersionCriteria(); LaunchSubScreen(theme, new GameInstanceListScreen(manager)); if (!prevInst.Equals(manager.CurrentInstance)) { // Game instance changed, reset everything plan.Reset(); registry = RegistryManager.Instance(manager.CurrentInstance).registry; RefreshList(theme); } else if (!SortedDictionaryEquals(registry.Repositories, prevRepos)) { // Repos changed, need to fetch them UpdateRegistry(theme, false); RefreshList(theme); } else if (!manager.CurrentInstance.VersionCriteria().Equals(prevVerCrit)) { // VersionCriteria changed, need to re-check what is compatible RefreshList(theme); } return(true); }
private bool Help(ConsoleTheme theme) { ModListHelpDialog hd = new ModListHelpDialog(); hd.Run(theme); DrawBackground(theme); return(true); }
private bool EditInstallFilters(ConsoleTheme theme) { LaunchSubScreen(theme, new InstallFiltersScreen( ServiceLocator.Container.Resolve <Configuration.IConfiguration>(), manager.CurrentInstance )); return(true); }
/// <summary> /// Show the screen. /// Luckily we don't have any interaction to do. /// </summary> public void Run(ConsoleTheme theme) { Draw(theme); // Try to return the terminal to normal Console.SetCursorPosition(0, Console.WindowHeight - 2); Console.ResetColor(); Console.CursorVisible = true; }
public ConsoleSink( ConsoleTheme theme, ITextFormatter formatter, LogEventLevel?standardErrorFromLevel) { _standardErrorFromLevel = standardErrorFromLevel; _theme = theme ?? throw new ArgumentNullException(nameof(theme)); _formatter = formatter; }
private bool AddMiniAVC(ConsoleTheme theme) { globalFilters = globalFilters .Concat(miniAVC) .Distinct() .ToList(); globalList.SetData(globalFilters); return(true); }
private bool UpgradeAll(ConsoleTheme theme) { foreach (string identifier in registry.Installed(true).Select(kvp => kvp.Key)) { if (registry.HasUpdate(identifier, manager.CurrentInstance.VersionCriteria())) { plan.Upgrade.Add(identifier); } } return(true); }
private void AddFilter(ConsoleTheme theme, ConsoleListBox <string> box, List <string> filters) { string filter = new InstallFilterAddDialog().Run(theme); DrawBackground(theme); if (!string.IsNullOrEmpty(filter) && !filters.Contains(filter)) { filters.Add(filter); box.SetData(filters); } }
int RenderValue(ConsoleTheme theme, ThemedValueFormatter valueFormatter, LogEventPropertyValue propertyValue, TextWriter output, string format) { if (_isLiteral && propertyValue is ScalarValue sv && sv.Value is string) { var count = 0; using (theme.Apply(output, ConsoleThemeStyle.String, ref count)) output.Write(sv.Value); return(count); } return(valueFormatter.Format(propertyValue, output, format, _isLiteral)); }
public static LoggerConfiguration MockConsoleForUser( this LoggerSinkConfiguration sinkConfiguration, LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose, string outputTemplate = "[{UserData}] {Message:lj}{NewLine}{Exception}", IFormatProvider formatProvider = null, LoggingLevelSwitch levelSwitch = null, LogEventLevel?standardErrorFromLevel = null, ConsoleTheme theme = null) { return(sinkConfiguration .Sink(new MockFormatSink(outputTemplate), LogEventLevel.Verbose, new LoggingLevelSwitch(LogEventLevel.Verbose))); }
/// <summary> /// Draw a cool retro splash screen like IBM used to do. /// </summary> /// <param name="theme">The visual theme to use to draw the dialog</param> /// <param name="pressAny">If true, ask user to press any key, otherwise say loading</param> private void Draw(ConsoleTheme theme, bool pressAny = false) { Console.CursorVisible = false; if (theme.SplashBg.HasValue) { Console.BackgroundColor = theme.SplashBg.Value; } else { Console.ResetColor(); } Console.Clear(); Console.ForegroundColor = theme.SplashAccentFg; string block = $"{Symbols.lowerHalfBlock}"; drawCentered(1, " ######## #### ##### ###### ##### ####".Replace("#", block)); drawCentered(2, " ######### #### ###### ########## ###### ####".Replace("#", block)); drawCentered(3, "#### ### ####### ### ### ###### ### ".Replace("#", block)); drawCentered(4, "#### ###### ########## ####### ### ".Replace("#", block)); drawCentered(5, "#### ###### ########## ### ####### ".Replace("#", block)); drawCentered(6, "#### ### ####### ### ### ### ###### ".Replace("#", block)); drawCentered(7, " ######### #### ###### #### #### #### ######".Replace("#", block)); drawCentered(8, " ######## #### ##### #### #### #### #####".Replace("#", block)); drawCentered(10, "Comprehensive Kerbal Archive Network"); Console.ForegroundColor = theme.SplashNormalFg; string horiz = $"{Symbols.horizLineDouble}"; drawCentered(12, $"{Symbols.upperLeftCornerDouble}##################################################{Symbols.upperRightCornerDouble}".Replace("#", horiz)); for (int ln = 13; ln <= 15; ++ln) { drawCentered(ln, $"{Symbols.vertLineDouble} {Symbols.vertLineDouble}"); } drawCentered(14, $"Version {Meta.GetVersion()}"); drawCentered(16, $"{Symbols.lowerLeftCornerDouble}##################################################{Symbols.lowerRightCornerDouble}".Replace("#", horiz)); drawCentered(18, $"(C) Copyright the CKAN Authors 2014-{DateTime.Now.Year}"); drawCentered(19, "https://github.com/KSP-CKAN/CKAN/graphs/contributors"); if (pressAny) { drawCentered(21, "Press any key to continue"); } else { drawCentered(21, "Loading..."); } }
public OutputTemplateRenderer(ConsoleTheme theme, string outputTemplate, IFormatProvider formatProvider) { if (outputTemplate == null) { throw new ArgumentNullException(nameof(outputTemplate)); } var template = new MessageTemplateParser().Parse(outputTemplate); var renderers = new List <OutputTemplateTokenRenderer>(); foreach (var token in template.Tokens) { if (token is TextToken tt) { renderers.Add(new TextTokenRenderer(theme, tt.Text)); continue; } var pt = (PropertyToken)token; if (pt.PropertyName == OutputProperties.LevelPropertyName) { renderers.Add(new LevelTokenRenderer(theme, pt)); } else if (pt.PropertyName == OutputProperties.NewLinePropertyName) { renderers.Add(new NewLineTokenRenderer(pt.Alignment)); } else if (pt.PropertyName == OutputProperties.ExceptionPropertyName) { renderers.Add(new ExceptionTokenRenderer(theme, pt)); } else if (pt.PropertyName == OutputProperties.MessagePropertyName) { renderers.Add(new MessageTemplateOutputTokenRenderer(theme, pt, formatProvider)); } else if (pt.PropertyName == OutputProperties.TimestampPropertyName) { renderers.Add(new TimestampTokenRenderer(theme, pt, formatProvider)); } else if (pt.PropertyName == "Properties") { renderers.Add(new PropertiesTokenRenderer(theme, pt, template, formatProvider)); } else { renderers.Add(new EventPropertyTokenRenderer(theme, pt, formatProvider)); } } _renderers = renderers.ToArray(); }
private bool UpdateRegistry(ConsoleTheme theme, bool showNewModsPrompt = true) { ProgressScreen ps = new ProgressScreen("Updating Registry", "Checking for updates"); LaunchSubScreen(theme, ps, (ConsoleTheme th) => { HashSet <string> availBefore = new HashSet <string>( Array.ConvertAll <CkanModule, string>( registry.CompatibleModules( manager.CurrentInstance.VersionCriteria() ).ToArray(), (l => l.identifier) ) ); recent.Clear(); try { Repo.UpdateAllRepositories( RegistryManager.Instance(manager.CurrentInstance), manager.CurrentInstance, manager.Cache, ps ); } catch (ReinstallModuleKraken rmk) { ChangePlan reinstPlan = new ChangePlan(); foreach (CkanModule m in rmk.Modules) { reinstPlan.ToggleUpgrade(m); } LaunchSubScreen(theme, new InstallScreen(manager, reinstPlan, debug)); } catch (Exception ex) { // There can be errors while you re-install mods with changed metadata ps.RaiseError(ex.Message + ex.StackTrace); } // Update recent with mods that were updated in this pass foreach (CkanModule mod in registry.CompatibleModules( manager.CurrentInstance.VersionCriteria() )) { if (!availBefore.Contains(mod.identifier)) { recent.Add(mod.identifier); } } }); if (showNewModsPrompt && recent.Count > 0 && RaiseYesNoDialog(newModPrompt(recent.Count))) { searchBox.Clear(); moduleList.FilterString = searchBox.Value = "~n"; } RefreshList(theme); return(true); }
private bool SelectInstall(ConsoleTheme theme) { GameInstance prevInst = manager.CurrentInstance; LaunchSubScreen(theme, new GameInstanceListScreen(manager)); // Abort if same instance as before if (!prevInst.Equals(manager.CurrentInstance)) { plan.Reset(); registry = RegistryManager.Instance(manager.CurrentInstance).registry; RefreshList(); } return(true); }
/// <summary> /// Configure standard input/output /// </summary> /// <param name="configuration"></param> /// <param name="outputTemplate"></param> /// <param name="theme"></param> /// <param name="restrictedToMinimumLevel"></param> /// <param name="formatProvider"></param> /// <param name="stdErrorFromLevel"></param> /// <returns><see cref="LoggerConfiguration"/></returns> public static LoggerConfiguration ConfigueStd(this LoggerSinkConfiguration configuration, string outputTemplate = DefaultOutputTemplate, ConsoleTheme theme = null, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, IFormatProvider formatProvider = null, LogEventLevel?stdErrorFromLevel = null ) { return(configuration.Console( outputTemplate: outputTemplate, formatProvider: formatProvider, standardErrorFromLevel: stdErrorFromLevel, theme: theme ?? SystemConsoleTheme.Literate, restrictedToMinimumLevel: restrictedToMinimumLevel)); }
private bool ViewMetadata(ConsoleTheme theme) { ConsoleMessageDialog md = new ConsoleMessageDialog( $"\"{mod.identifier}\": {registry.GetAvailableMetadata(mod.identifier)}", new List <string> { "OK" }, () => $"{mod.name} Metadata", TextAlign.Left ); md.Run(theme); DrawBackground(theme); return(true); }
private bool ExportInstalled(ConsoleTheme theme) { try { // Save the mod list as "depends" without the installed versions. // Beacause that's supposed to work. RegistryManager.Instance(manager.CurrentInstance).Save(true); string path = Path.Combine( manager.CurrentInstance.CkanDir(), $"installed-{manager.CurrentInstance.Name}.ckan" ); RaiseError($"Mod list exported to {path}"); } catch (Exception ex) { RaiseError($"Export failed: {ex.Message}"); } return(true); }
/// <summary> /// Launch a URL in the system browser. /// </summary> /// <param name="theme">The visual theme to use to draw the dialog</param> /// <param name="u">URL to launch</param> /// <returns> /// True. /// </returns> public static bool LaunchURL(ConsoleTheme theme, Uri u) { // I'm getting error output on Linux, because this runs xdg-open which // calls chromium-browser which prints a bunch of stuff about plugins that // no one cares about. Which corrupts the screen. // But redirecting stdout requires UseShellExecute=false, which doesn't // support launching URLs! .NET's API design has painted us into a corner. // So instead we display a popup dialog for the garbage to print all over, // then wait 1.5 seconds and refresh the screen when it closes. ConsoleMessageDialog d = new ConsoleMessageDialog("Launching...", new List <string>()); d.Run(theme, (ConsoleTheme th) => { Utilities.ProcessStartURL(u.ToString()); System.Threading.Thread.Sleep(1500); }); return(true); }
private bool ViewSuggestions(ConsoleTheme theme) { ChangePlan reinstall = new ChangePlan(); foreach (InstalledModule im in registry.InstalledModules) { // Only check mods that are still available try { if (registry.LatestAvailable(im.identifier, manager.CurrentInstance.VersionCriteria()) != null) { reinstall.Install.Add(im.Module); } } catch { // The registry object badly needs an IsAvailable check } } try { DependencyScreen ds = new DependencyScreen(manager, reinstall, new HashSet <string>(), debug); if (ds.HaveOptions()) { LaunchSubScreen(theme, ds); bool needRefresh = false; // Copy the right ones into our real plan foreach (CkanModule mod in reinstall.Install) { if (!registry.IsInstalled(mod.identifier, false)) { plan.Install.Add(mod); needRefresh = true; } } if (needRefresh) { RefreshList(); } } else { RaiseError("Installed mods have no unsatisfied recommendations or suggestions."); } } catch (ModuleNotFoundKraken k) { RaiseError($"{k.module} {k.version}: {k.Message}"); } return(true); }
/// <summary> /// Show the splash screen and wait for a key press. /// </summary> /// <param name="theme">The visual theme to use to draw the dialog</param> public bool Run(ConsoleTheme theme) { // If there's a default instance, try to get the lock for it. GameInstance ksp = manager.CurrentInstance ?? manager.GetPreferredInstance(); if (ksp != null && !GameInstanceListScreen.TryGetInstance(theme, ksp, (ConsoleTheme th) => Draw(th, false))) { Console.ResetColor(); Console.Clear(); Console.CursorVisible = true; return(false); } // Draw screen with press any key Draw(theme, true); // Wait for a key Console.ReadKey(true); return(true); }
private bool CaptureKey(ConsoleTheme theme) { ConsoleKeyInfo k = default(ConsoleKeyInfo); ConsoleMessageDialog keyprompt = new ConsoleMessageDialog("Press a key", new List <string>()); keyprompt.Run(theme, (ConsoleTheme th) => { k = Console.ReadKey(true); }); ConsoleMessageDialog output = new ConsoleMessageDialog( $"Key: {k.Key,18}\nKeyChar: 0x{(int)k.KeyChar:x2}\nModifiers: {k.Modifiers,12}", new List <string> { "OK" } ); output.Run(theme); return(true); }