From 6ae94d33b0fa04fb99e03b6e4d4a0784866786af Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 21 Dec 2019 23:45:23 +0100 Subject: [PATCH] add basic input navigation, newlines are broken for now --- telegram/Command.cs | 6 +-- telegram/Util.cs | 57 +++++++++++++++++++++++++++ telegram/tgcli.cs | 93 +++++++++++++++++++++++++++++++++------------ 3 files changed, 128 insertions(+), 28 deletions(-) diff --git a/telegram/Command.cs b/telegram/Command.cs index 16a20dd..9493ca5 100644 --- a/telegram/Command.cs +++ b/telegram/Command.cs @@ -629,8 +629,8 @@ namespace telegram { public override void Handler(List inputParams) { try { if (inputParams.Count == 0) { - currentInputLine = "/e " + ((TdApi.MessageContent.MessageText) lastMessage?.Content)?.Text?.Text; - Emojis.ForEach(em => currentInputLine = currentInputLine.Replace(em.Item2, em.Item1)); + SetInputLine("/e " + ((TdApi.MessageContent.MessageText) lastMessage?.Content)?.Text?.Text); + Emojis.ForEach(em => SetInputLine(currentInputLine.Replace(em.Item2, em.Item1))); return; } @@ -702,7 +702,7 @@ namespace telegram { return; } - currentInputLine = $"/rd {result.Id} "; + SetInputLine($"/rd {result.Id} "); } catch { lock (@lock) diff --git a/telegram/Util.cs b/telegram/Util.cs index 77c1f5e..548dd7c 100644 --- a/telegram/Util.cs +++ b/telegram/Util.cs @@ -377,6 +377,63 @@ namespace telegram { new Tuple(":shrugm:", Emoji.ManShrugging.Sequence.AsString) }; + public static void InsertToInputLine(string strToInsert) { + var part1 = currentInputLine.Substring(0, currentInputPos); + var part2 = currentInputLine.Substring(currentInputPos); + currentInputLine = part1 + strToInsert + part2; + currentInputPos += strToInsert.Length; + } + + public static void SetInputLine(string newInputLine) { + currentInputLine = newInputLine; + currentInputPos = newInputLine.Length; + } + + public static void RemoveFromInputLine(bool word = false) { + var part1 = currentInputLine.Substring(0, currentInputPos); + var oldlen = part1.Length; + var part2 = currentInputLine.Substring(currentInputPos); + if (word) { + var lastIndex = part1.TrimEnd().LastIndexOf(" ", StringComparison.Ordinal); + if (lastIndex < 0) + lastIndex = 0; + part1 = part1.Substring(0, lastIndex); + if (lastIndex != 0) + part1 += " "; + //if (part1.EndsWith("⏎")) + // part1 = part1.Remove(part1.Length - 1); + + var newlen = part1.Length; + + currentInputLine = part1 + part2; + currentInputPos -= oldlen - newlen; + return; + } + + currentInputLine = part1.Substring(0, part1.Length - 1) + part2; + currentInputPos--; + } + + public static void RemoveFromInputLineForward(bool word = false) { + var part1 = currentInputLine.Substring(0, currentInputPos); + var part2 = currentInputLine.Substring(currentInputPos); + if (word) { + var index = part2.IndexOf(" ", StringComparison.Ordinal); + if (index < 0) + index = part2.Length - 1; + part2 = part2.Substring(0, index); + if (index != 0) + part2 = " " + part2; + //if (part2.StartsWith("⏎")) + // part2 = part2.Remove(part1.Length - 1); + + currentInputLine = part1 + part2; + return; + } + + currentInputLine = part1 + part2.Substring(1); + } + public static readonly List SpecialKeys = new List { ConsoleKey.Backspace, ConsoleKey.Tab, diff --git a/telegram/tgcli.cs b/telegram/tgcli.cs index 6122662..465e660 100644 --- a/telegram/tgcli.cs +++ b/telegram/tgcli.cs @@ -13,12 +13,10 @@ using static telegram.CommandManager; namespace telegram { /* * TODO: + * fix newlines with input nav... * unreads are unreliable in secret chats! * mute,unmute chats * photo & document download & show externally - * cursor input nav (up/down history, (alt +) left/right) - * ref: http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#cursor-navigation - * ref: https://en.wikipedia.org/wiki/ANSI_escape_code#Escape_sequences * refactor everything * re-evaluate ClearCurrentConsoleLine function * When TDLib 1.6 is released: implement contacts @@ -36,9 +34,10 @@ namespace telegram { public static volatile Td.TdApi.Message lastMessage; public static volatile bool quitting; public static volatile string currentInputLine = ""; - public static volatile List messageQueue = new List(); - public static volatile List missedMessages = new List(); - public static volatile string prefix = "[tgcli"; + public static volatile int currentInputPos; + public static volatile List messageQueue = new List(); + public static volatile List missedMessages = new List(); + public static volatile string prefix = "[tgcli"; public static volatile bool silent; public static volatile object @lock = new object(); @@ -195,8 +194,10 @@ namespace telegram { else output += "]"; output += " > "; + var prefixlen = GetActualStringWidth(output); output += TruncateMessageStart(currentInputLine, Console.LargestWindowWidth - GetActualStringWidth(output)); Console.Write(output); + Console.Write($"\u001b[{currentInputPos + prefixlen + 1}G"); } } @@ -209,7 +210,7 @@ namespace telegram { break; case ConsoleKey.Enter when currentInputLine.StartsWith("/"): { var command = currentInputLine.Substring(1); - currentInputLine = ""; + SetInputLine(""); HandleCommand(command); ScreenUpdate(); return; @@ -222,36 +223,74 @@ namespace telegram { } case ConsoleKey.Enter: SendMessage(currentInputLine, currentChatId); - currentInputLine = ""; + SetInputLine(""); ScreenUpdate(); break; - case ConsoleKey.Backspace when currentInputLine.Length >= 1: + case ConsoleKey.Backspace when currentInputLine.Length >= 1 && currentInputPos >= 1: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { - var lastIndex = currentInputLine.TrimEnd().LastIndexOf(" ", StringComparison.Ordinal); - if (lastIndex < 0) - lastIndex = 0; - currentInputLine = currentInputLine.Substring(0, lastIndex); - if (lastIndex != 0) - currentInputLine += " "; - if (currentInputLine.EndsWith("⏎")) - currentInputLine = currentInputLine.Remove(currentInputLine.Length - 1); + RemoveFromInputLine(true); ScreenUpdate(); return; } - currentInputLine = currentInputLine.Substring(0, currentInputLine.Length - 1); - if (currentInputLine.EndsWith("⏎")) - currentInputLine = currentInputLine.Remove(currentInputLine.Length - 1); + RemoveFromInputLine(); + //if (currentInputLine.EndsWith("⏎")) + // currentInputLine = currentInputLine.Remove(currentInputLine.Length - 1); ScreenUpdate(); break; + case ConsoleKey.Delete when currentInputLine.Length >= 1 && currentInputPos < currentInputLine.Length: + if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { + RemoveFromInputLineForward(true); + ScreenUpdate(); + return; + } + + RemoveFromInputLineForward(); + //if (currentInputLine.EndsWith("⏎")) + // currentInputLine = currentInputLine.Remove(currentInputLine.Length - 1); + ScreenUpdate(); + break; + case ConsoleKey.LeftArrow when key.Modifiers.HasFlag(ConsoleModifiers.Shift): + if (currentInputPos == 0) + break; + + var part1 = currentInputLine.Substring(0, currentInputPos); + var lastIndex = part1.TrimEnd().LastIndexOf(" ", StringComparison.Ordinal); + if (lastIndex < 0) + lastIndex = 0; + currentInputPos = lastIndex; + ScreenUpdate(); + break; + case ConsoleKey.RightArrow when key.Modifiers.HasFlag(ConsoleModifiers.Shift): + if (currentInputPos >= currentInputLine.Length) + break; + + var index = currentInputLine.IndexOf(" ", currentInputPos + 1, StringComparison.Ordinal); + currentInputPos = index + 1; + if (index < 0) + currentInputPos = currentInputLine.Length; + ScreenUpdate(); + break; + case ConsoleKey.LeftArrow: + if (currentInputPos > 0) + currentInputPos--; + ScreenUpdate(); + break; + case ConsoleKey.RightArrow: + if (currentInputPos < currentInputLine.Length) + currentInputPos++; + ScreenUpdate(); + break; + case ConsoleKey.UpArrow: break; + case ConsoleKey.DownArrow: break; default: { switch (key.Key) { case ConsoleKey.N when key.Modifiers.HasFlag(ConsoleModifiers.Control): - currentInputLine += "⏎ "; + InsertToInputLine("⏎ "); ScreenUpdate(); return; case ConsoleKey.D when key.Modifiers.HasFlag(ConsoleModifiers.Control): - HandleCommand("q"); + HandleCommand(currentChatId == 0 ? "q" : "c"); ScreenUpdate(); return; case ConsoleKey.Q when key.Modifiers.HasFlag(ConsoleModifiers.Control): @@ -267,8 +306,12 @@ namespace telegram { ScreenUpdate(); return; case ConsoleKey.O when key.Modifiers.HasFlag(ConsoleModifiers.Control): - if (string.IsNullOrWhiteSpace(currentInputLine)) - currentInputLine = "/o "; + SetInputLine(currentInputLine switch { + "/o " => "/os ", + "/os " => "/o ", + "" => "/o ", + _ => currentInputLine + }); ScreenUpdate(); return; case ConsoleKey.L when key.Modifiers.HasFlag(ConsoleModifiers.Control): @@ -278,7 +321,7 @@ namespace telegram { } if (!SpecialKeys.Contains(key.Key)) { - currentInputLine += key.KeyChar; + InsertToInputLine(key.KeyChar.ToString()); ScreenUpdate(); }