/// <summary> /// Writes a collection of item for selecting. /// </summary> /// <typeparam name="T">The type of data.</typeparam> /// <param name="cli">The command line interface proxy.</param> /// <param name="collection">The collection data.</param> /// <param name="options">The selection display options.</param> /// <param name="select">The index of item selected.</param> /// <returns>The result of selection.</returns> private static SelectionResult <T> Select <T>(StyleConsole cli, SelectionData <T> collection, SelectionConsoleOptions options, int select) { var temp = (0, 0, 0, 0, false, false, 0, 0); var oldSelect = select; while (true) { var list = collection.ToList(); void resetSelect() { if (oldSelect < 0 || oldSelect >= list.Count) { return; } var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); var oldItem = list[oldSelect]; var y2 = Math.DivRem(oldSelect % temp.Item7, temp.Item4, out var x2) - h; x2 *= temp.Item8; cli.MoveCursorBy(x2, y2); RenderData(cli, oldItem, options, false, temp.Item8); cli.MoveCursorBy(-x2 - temp.Item8, -y2); }; if (temp.Item3 > 0 && select >= temp.Item1 && select < (temp.Item1 + temp.Item2)) { cli.BackspaceToBeginning(); var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); if (oldSelect != select) { resetSelect(); } if (select < 0 || select >= list.Count) { select = 0; } var item = list[select]; var y = Math.DivRem(select % temp.Item7, temp.Item4, out var x) - h; x *= temp.Item8; cli.MoveCursorBy(x, y); RenderData(cli, item, options, true, temp.Item8); cli.MoveCursorBy(-x - temp.Item8, -y); RenderSelectResult(cli, item?.Title, options); } else { if (temp.Item3 > 0) { cli.BackspaceToBeginning(); var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); for (var i = 0; i < h; i++) { cli.MoveCursorBy(0, -1); cli.Clear(StyleConsole.RelativeAreas.Line); } } temp = RenderData(cli, list, options, select); } oldSelect = select; ConsoleKeyInfo key; try { key = cli.ReadKey(); } catch (InvalidOperationException) { return(SelectByManualTyping(cli, collection, options)); } catch (IOException) { return(SelectByManualTyping(cli, collection, options)); } catch (SecurityException) { return(SelectByManualTyping(cli, collection, options)); } catch (NotSupportedException) { return(SelectByManualTyping(cli, collection, options)); } switch (key.Key) { case ConsoleKey.Enter: case ConsoleKey.Select: case ConsoleKey.Spacebar: if (select < 0 || select >= list.Count) { select = temp.Item1; if (select < 0 || select >= list.Count) { select = 0; } break; } var sel = list[select]; RenderSelectResult(cli, sel?.Title, options); cli.WriteLine(); return(new SelectionResult <T>(sel.Title, select, sel.Data, sel.Title)); case ConsoleKey.Backspace: case ConsoleKey.Delete: case ConsoleKey.Clear: cli.WriteImmediately(' '); cli.BackspaceToBeginning(); resetSelect(); return(SelectByManualTyping(cli, collection, options)); case ConsoleKey.Escape: case ConsoleKey.Pause: cli.WriteImmediately(' '); cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, null, options); cli.WriteLine(); return(new SelectionResult <T>(string.Empty, SelectionResultTypes.Canceled)); case ConsoleKey.Help: case ConsoleKey.F1: { cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, "?", options); cli.WriteLine(); var item = collection.Get('?', out select); return(item == null ? new SelectionResult <T>("?", SelectionResultTypes.Selected) : new SelectionResult <T>("?", select, item.Data, item.Title)); } case ConsoleKey.F4: if (temp.Item3 > 0) { cli.BackspaceToBeginning(); var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); for (var i = 0; i < h; i++) { cli.MoveCursorBy(0, -1); cli.Clear(StyleConsole.RelativeAreas.Line); } } return(SelectByManualTyping(cli, collection, options, true)); case ConsoleKey.F5: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } break; case ConsoleKey.F6: cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, null, options); cli.WriteLine(); if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } temp = RenderData(cli, list, options, select); break; case ConsoleKey.F12: { cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, "?", options); cli.WriteLine(); var item = collection.Get('?', out select); return(item == null ? new SelectionResult <T>("?", SelectionResultTypes.Canceled) : new SelectionResult <T>("?", select, item.Data, item.Title)); } case ConsoleKey.PageUp: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } else { select = Math.Max(0, temp.Item1 - temp.Item7); } break; case ConsoleKey.PageDown: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = list.Count - 1; } else { select = Math.Min(list.Count - 1, temp.Item1 + temp.Item7); } break; case ConsoleKey.UpArrow: if (select < temp.Item4) { select += list.Count - (list.Count % temp.Item4); if (select >= list.Count) { select -= temp.Item4; } if (select >= list.Count) { select = list.Count - 1; } else if (select < 0) { select = 0; } } else { select -= temp.Item4; } break; case ConsoleKey.DownArrow: select += temp.Item4; if (select >= list.Count) { select %= temp.Item4; if (select >= list.Count) { select = list.Count - 1; } } break; case ConsoleKey.LeftArrow: select--; if (select < 0) { select = list.Count - 1; } break; case ConsoleKey.RightArrow: select++; if (select >= list.Count) { select = 0; } break; case ConsoleKey.Home: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } else { select = temp.Item1; } break; case ConsoleKey.End: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = list.Count - 1; } else { select = temp.Item1 + temp.Item2 - 1; } break; default: { var item = collection.Get(key.KeyChar, out select); if (item == null) { select = oldSelect; continue; } cli.WriteImmediately(' '); cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, item.Title, options); cli.WriteLine(); return(new SelectionResult <T>(item.Title, select, item.Data, item.Title)); } } } }
private static string RenderData(StyleConsole cli, ConsoleProgressStyle style, string caption, OneProgress value, string status) { var maxWidth = GetBufferSafeWidth(cli); var width = style.Size switch { ConsoleProgressStyle.Sizes.None => 0, ConsoleProgressStyle.Sizes.Short => maxWidth > 70 ? 20 : 10, ConsoleProgressStyle.Sizes.Wide => maxWidth > 88 ? 60 : 40, ConsoleProgressStyle.Sizes.Full => maxWidth - 5, _ => maxWidth > 70 ? (maxWidth > 88 ? 40 : 30) : 20 }; var barChar = style.Kind switch { ConsoleProgressStyle.Kinds.AngleBracket => '>', ConsoleProgressStyle.Kinds.Plus => '+', ConsoleProgressStyle.Kinds.Sharp => '#', ConsoleProgressStyle.Kinds.X => 'x', ConsoleProgressStyle.Kinds.O => 'o', _ => ' ', }; var pendingChar = style.Kind switch { ConsoleProgressStyle.Kinds.AngleBracket => '=', ConsoleProgressStyle.Kinds.Plus => '-', ConsoleProgressStyle.Kinds.Sharp => '-', ConsoleProgressStyle.Kinds.X => '.', ConsoleProgressStyle.Kinds.O => '.', _ => ' ', }; var col = new List <ConsoleText>(); if (!string.IsNullOrWhiteSpace(caption)) { var sb = new StringBuilder(); var j = style.IgnoreCaptionSeparator ? 0 : 1; foreach (var c in caption) { var c2 = c; switch (c) { case '\t': case '\r': case '\n': j++; c2 = ' '; break; case '\0': case '\b': continue; default: j += GetLetterWidth(c); break; } sb.Append(c2); } if (!style.IgnoreCaptionSeparator) { sb.Append(' '); } col.Add(sb, new ConsoleTextStyle(style.CaptionRgbColor, style.CaptionConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); if (style.Size == ConsoleProgressStyle.Sizes.Full) { width -= j; } } var v = value?.Value ?? -1; if (v > 1) { v = 1; } if (double.IsNaN(v)) { cli.WriteLine(col); return(null); } var w = (int)Math.Round(width * v); if (w < 0) { w = 0; } var isError = value?.IsFailed == true || value?.IsNotSupported == true; var isSucc = !isError && value?.IsSuccessful == true; var newStatus = $"{(isError ? "e" : (isSucc ? "s" : "p"))}{w}/{maxWidth}"; if (status == newStatus) { cli.Flush(); cli.MoveCursorBy(0, 1); return(status); } if (barChar == ' ') { col.Add(barChar, w, new ConsoleTextStyle(null, null, isError ? style.ErrorRgbColor : style.BarRgbColor, isError ? style.ErrorConsoleColor : style.BarConsoleColor)); col.Add(pendingChar, width - w, new ConsoleTextStyle(null, null, style.PendingRgbColor, style.PendingConsoleColor)); } else { col.Add(barChar, w, new ConsoleTextStyle(isError ? style.ErrorRgbColor : style.BarRgbColor, isError ? style.ErrorConsoleColor : style.BarConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); col.Add(pendingChar, width - w, new ConsoleTextStyle(style.PendingRgbColor, style.PendingConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); } if (v >= 0) { var s = v.ToString("#0%"); if (s.Length > 3) { s = isSucc ? " √" : "99%"; } col.Add(" " + s, new ConsoleTextStyle(style.ValueRgbColor, style.ValueConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); } cli.Flush(); cli.Clear(StyleConsole.RelativeAreas.Line); cli.BackspaceToBeginning(); cli.WriteLine(col); return(status); } }