2019-12-10 09:07:46 +01:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2019-12-12 18:55:43 +01:00
using System.Threading ;
2019-12-11 13:17:35 +01:00
using NeoSmart.Unicode ;
2019-12-10 09:07:46 +01:00
using static TdLib . TdApi ;
2023-01-14 04:32:36 +01:00
using static tgcli . tgcli ;
2019-12-10 09:07:46 +01:00
2023-01-23 17:52:01 +01:00
namespace tgcli ;
public static class Util {
public static class Ansi {
public const string ResetAll = "\x1B[0m" ;
public const string Red = "\x1b[31m" ;
public const string Green = "\x1b[32m" ;
public const string Yellow = "\x1b[33m" ;
public const string Blue = "\x1b[34m" ;
public const string Magenta = "\x1b[35m" ;
public const string Cyan = "\x1b[36m" ;
public const string Bold = "\x1b[1m" ;
public const string BoldOff = "\x1b[22m" ;
public const string Inverse = "\x1b[7m" ;
public const string InverseOff = "\x1b[27m" ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static User GetUser ( long uid ) {
try {
var uinfo = client . ExecuteAsync ( new GetUser { UserId = uid } ) . Result ;
return uinfo ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
catch {
var user = new User ( ) ;
user . FirstName = "null" ;
user . LastName = "null" ;
return user ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static Chat GetChat ( long chatId ) {
try {
return client . ExecuteAsync ( new GetChat { ChatId = chatId } ) . Result ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
catch {
return null ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static User GetMe ( ) {
return client . ExecuteAsync ( new GetMe ( ) ) . Result ;
}
public static Message GetMessage ( long chatId , long messageId ) {
return client . ExecuteAsync ( new GetMessage { ChatId = chatId , MessageId = messageId } ) . Result ;
}
public static int GetTotalMessages ( long chatId ) {
try {
var response = client . ExecuteAsync ( new SearchChatMessages { ChatId = chatId , Query = "+" , Limit = 1 } ) ;
return response . Result . TotalCount ;
}
catch {
return 9999 ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static List < Message > GetHistory ( long chatId , int limit = 5 , long fromMessageId = 0 , int offset = 0 , bool isSecret = false , bool skipTotal = false ) {
var history = new List < Message > ( ) ;
var total = GetTotalMessages ( chatId ) ;
var chat = GetChat ( chatId ) ;
if ( chat . Type is ChatType . ChatTypeSupergroup | | isSecret )
skipTotal = true ;
if ( limit > total & & ! skipTotal )
limit = total ;
for ( var i = 5 ; i > 0 ; i - - ) {
if ( limit < = 0 ) {
if ( total = = 0 )
2019-12-15 15:03:20 +01:00
return history ;
2023-01-23 17:52:01 +01:00
lock ( @lock )
messageQueue . Add ( $"{Ansi.Red}[tgcli] " + "Limit cannot be less than one. Usage: /history <count>" ) ;
2019-12-15 15:03:20 +01:00
return history ;
}
2023-01-23 17:52:01 +01:00
var response = client . ExecuteAsync ( new GetChatHistory {
ChatId = chatId ,
FromMessageId = fromMessageId ,
Limit = limit ,
Offset = offset ,
OnlyLocal = false
} )
. Result ;
if ( response . Messages_ . Length < limit & & i > 1 & & ! isSecret ) {
Thread . Sleep ( 100 ) ;
continue ;
}
history . AddRange ( response . Messages_ ) ;
history . Reverse ( ) ;
2019-12-15 15:03:20 +01:00
return history ;
}
2023-01-18 04:02:17 +01:00
2023-01-23 17:52:01 +01:00
return history ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static bool IsMuted ( Chat c ) {
if ( c . NotificationSettings . MuteFor = = 0 & & ! c . NotificationSettings . UseDefaultMuteFor )
return false ;
NotificationSettingsScope scope = c . Type switch {
ChatType . ChatTypeBasicGroup = > new NotificationSettingsScope . NotificationSettingsScopeGroupChats ( ) ,
ChatType . ChatTypeSupergroup t = > t . IsChannel
? new NotificationSettingsScope . NotificationSettingsScopeChannelChats ( )
: new NotificationSettingsScope . NotificationSettingsScopeGroupChats ( ) ,
ChatType . ChatTypePrivate = > new NotificationSettingsScope . NotificationSettingsScopePrivateChats ( ) ,
ChatType . ChatTypeSecret = > new NotificationSettingsScope . NotificationSettingsScopePrivateChats ( ) ,
_ = > throw new ArgumentOutOfRangeException ( )
} ;
2019-12-17 12:04:56 +01:00
2023-01-23 17:52:01 +01:00
return client . GetScopeNotificationSettingsAsync ( scope ) . Result . MuteFor ! = 0 ;
}
2019-12-17 12:04:56 +01:00
2023-01-23 17:52:01 +01:00
public static List < Chat > GetUnreadChats ( bool all = false ) {
var output = new List < Chat > ( ) ;
var response = client . ExecuteAsync ( new GetChats { Limit = int . MaxValue } ) . Result ;
output . AddRange ( all
? response . ChatIds . Select ( GetChat ) . Where ( c = > c . UnreadCount > 0 | | c . IsMarkedAsUnread ) . ToList ( )
: response . ChatIds . Select ( GetChat ) . Where ( c = > ( c . UnreadCount > 0 | | c . IsMarkedAsUnread ) & & ! IsMuted ( c ) ) . ToList ( ) ) ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return output ;
}
public static List < Chat > GetChats ( ) {
var response = client . ExecuteAsync ( new GetChats { Limit = int . MaxValue } ) . Result ;
return response . ChatIds . Select ( GetChat ) . ToList ( ) ;
}
public static List < Chat > SearchChatsGlobal ( string query ) {
if ( query . TrimStart ( '@' ) . Length < 5 ) {
return new List < Chat > ( ) ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
var response = client . ExecuteAsync ( new SearchPublicChats { Query = query } ) . Result ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
var chats = response . ChatIds . Select ( GetChat ) . ToList ( ) ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
chats . AddRange ( client . ExecuteAsync ( new SearchChats { Query = query , Limit = int . MaxValue } ) . Result . ChatIds . Select ( GetChat ) ) ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return chats ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static Chat GetChatByUsernameGlobal ( string username ) {
try {
var response = client . ExecuteAsync ( new SearchPublicChat { Username = username } ) . Result ;
return response ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
catch {
return null ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static long GetUserIdByUsername ( string username ) {
try {
var response = client . ExecuteAsync ( new SearchPublicChat { Username = username } ) . Result ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
if ( response . Type is ChatType . ChatTypePrivate priv )
return priv . UserId ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return 0 ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
catch {
return 0 ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void AddUserToContacts ( int userId , string name ) {
//TODO implement when TDLib 1.6 is released
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static List < Chat > GetSecretChats ( ) {
var response = client . ExecuteAsync ( new GetChats { Limit = int . MaxValue } ) . Result ;
return response . ChatIds . Select ( GetChat ) . Where ( c = > c . Type is ChatType . ChatTypeSecret ) . ToList ( ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void CloseSecretChat ( int secretChatId ) {
client . ExecuteAsync ( new CloseSecretChat { SecretChatId = secretChatId } ) . Wait ( ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static Chat CreateSecretChat ( long userId ) {
return client . ExecuteAsync ( new CreateNewSecretChat { UserId = userId } ) . Result ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void DeleteChatHistory ( long chatId ) {
client . ExecuteAsync ( new DeleteChatHistory { ChatId = chatId , RemoveFromChatList = true , Revoke = true } ) . Wait ( ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static SecretChat GetSecretChat ( int secretChatId ) {
var response = client . ExecuteAsync ( new GetSecretChat { SecretChatId = secretChatId } ) . Result ;
return response ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void ClearCurrentConsoleLine ( ) {
Console . Write ( "\u001b[2K\r" ) ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
//Console.SetCursorPosition(0, Console.WindowHeight);
//Console.Write(new string(' ', Console.WindowWidth));
//Console.SetCursorPosition(0, Console.WindowHeight);
}
public static string ReadConsolePassword ( ) {
var pass = "" ;
do {
var key = Console . ReadKey ( true ) ;
if ( key . Key ! = ConsoleKey . Backspace & & key . Key ! = ConsoleKey . Enter ) {
pass + = key . KeyChar ;
Console . Write ( "*" ) ;
}
else {
if ( key . Key = = ConsoleKey . Backspace & & pass . Length > 0 ) {
2023-01-23 17:55:50 +01:00
pass = pass [ . . ^ 1 ] ;
2023-01-23 17:52:01 +01:00
Console . Write ( "\b \b" ) ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
else if ( key . Key = = ConsoleKey . Enter ) {
break ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
} while ( true ) ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
Console . WriteLine ( ) ;
return pass ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void SendMessage ( string message , long chatId , long replyTo = 0 ) {
if ( string . IsNullOrWhiteSpace ( message ) )
return ;
Emojis . ForEach ( em = > message = message . Replace ( em . Item1 , em . Item2 ) ) ;
client . ExecuteAsync ( new SendMessage {
2023-01-23 17:55:50 +01:00
ChatId = chatId , InputMessageContent = new InputMessageContent . InputMessageText { Text = new FormattedText { Text = message } } , ReplyToMessageId = replyTo ,
2023-01-23 17:52:01 +01:00
} ) ;
currentUserRead = false ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static Message EditMessage ( string newText , Message message ) {
Emojis . ForEach ( em = > newText = newText . Replace ( em . Item1 , em . Item2 ) ) ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
var msg = client . ExecuteAsync ( new EditMessageText {
ChatId = message . ChatId ,
MessageId = message . Id ,
InputMessageContent = new InputMessageContent . InputMessageText { Text = new FormattedText { Text = newText } }
} )
. Result ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return msg ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void MarkRead ( long chatId , long messageId ) {
client . ExecuteAsync ( new ViewMessages { ChatId = chatId , MessageIds = new [ ] { messageId } , ForceRead = true } ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static void MarkUnread ( long chatId ) {
client . ExecuteAsync ( new ToggleChatIsMarkedAsUnread { ChatId = chatId , IsMarkedAsUnread = true , } ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static long SearchChatId ( string query ) {
try {
var results = client . ExecuteAsync ( new SearchChats { Query = query , Limit = 5 } ) . Result ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return query . StartsWith ( "@" )
2023-01-23 17:55:50 +01:00
? results . ChatIds . First ( p = > GetChat ( p ) . Type is ChatType . ChatTypePrivate type & & GetUser ( type . UserId ) . Usernames . ActiveUsernames . Contains ( query [ 1. . ] ) )
2023-01-23 17:52:01 +01:00
: results . ChatIds . First ( p = > ! ( GetChat ( p ) . Type is ChatType . ChatTypeSecret ) ) ;
}
catch {
lock ( @lock )
messageQueue . Add ( $"{Ansi.Red}[tgcli] No results found." ) ;
return 0 ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static long SearchUserInChats ( string query ) {
var results = client . ExecuteAsync ( new SearchChatsOnServer { Query = query , Limit = 5 } ) . Result ;
if ( results . ChatIds . Length = = 0 )
return 0 ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
var output = results . ChatIds . Select ( GetChat ) . Where ( p = > p . Type is ChatType . ChatTypePrivate ) . Select ( p = > ( ( ChatType . ChatTypePrivate ) p . Type ) . UserId ) ;
return output . Any ( ) ? output . First ( ) : 0 ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static long SearchContacts ( string query ) {
//TODO implement when TDLib 1.6 is released
try {
var results = client . ExecuteAsync ( new SearchContacts { Query = query , Limit = 5 } ) . Result ;
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return query . StartsWith ( "@" ) ? results . UserIds . First ( p = > GetUser ( p ) . Usernames . ActiveUsernames . Contains ( query [ 1. . ] ) ) : results . UserIds . First ( ) ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
catch {
2019-12-15 15:03:20 +01:00
lock ( @lock )
2023-01-23 17:52:01 +01:00
messageQueue . Add ( $"{Ansi.Red}[tgcli] No results found." ) ;
return 0 ;
2023-01-14 04:32:36 +01:00
}
2023-01-23 17:52:01 +01:00
}
2023-01-14 04:32:36 +01:00
2023-01-23 17:52:01 +01:00
public static void LogOut ( ) {
lock ( @lock )
messageQueue . Add ( $"{Ansi.Yellow}[tgcli] Logging out..." ) ;
client . ExecuteAsync ( new LogOut ( ) ) . Wait ( ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static string GetFormattedUsername ( MessageSender sender ) {
return sender switch {
MessageSender . MessageSenderUser user = > GetFormattedUsername ( GetUser ( user . UserId ) ) ,
MessageSender . MessageSenderChat chat = > GetFormattedUsername ( GetChat ( chat . ChatId ) ) ,
_ = > throw new InvalidCastException ( )
} ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
private static string GetFormattedUsername ( User sender ) {
var username = sender . Usernames ? . ActiveUsernames ? . FirstOrDefault ( ) ;
if ( string . IsNullOrWhiteSpace ( username ) )
username = sender . FirstName + " " + sender . LastName ;
else
username = "@" + username ;
2023-01-14 04:32:36 +01:00
2023-01-23 17:52:01 +01:00
return username ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
private static string GetFormattedUsername ( Chat sender ) {
return $"{sender.Title} [as chat]" ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static string FormatTime ( long unix ) {
var time = DateTimeOffset . FromUnixTimeSeconds ( unix ) . DateTime . ToLocalTime ( ) ;
var currentTime = DateTime . Now . ToLocalTime ( ) ;
return time . ToString ( time . Date . Ticks = = currentTime . Date . Ticks ? "HH:mm" : "yyyy-MM-dd HH:mm" ) ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static bool IsMessageRead ( long chatId , long messageId ) {
var chat = GetChat ( chatId ) ;
return chat . LastReadOutboxMessageId > = messageId ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static int GetActualStringWidth ( string input ) {
input = input . Replace ( Ansi . Blue , "" ) ;
input = input . Replace ( Ansi . Bold , "" ) ;
input = input . Replace ( Ansi . Cyan , "" ) ;
input = input . Replace ( Ansi . Green , "" ) ;
input = input . Replace ( Ansi . Magenta , "" ) ;
input = input . Replace ( Ansi . Red , "" ) ;
input = input . Replace ( Ansi . Yellow , "" ) ;
input = input . Replace ( Ansi . Bold , "" ) ;
input = input . Replace ( Ansi . BoldOff , "" ) ;
input = input . Replace ( Ansi . Inverse , "" ) ;
input = input . Replace ( Ansi . InverseOff , "" ) ;
input = input . Replace ( Ansi . ResetAll , "" ) ;
return input . Length ;
}
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
public static string GetFormattedStatus ( bool isRead ) {
var output = " " ;
output + = ( isRead ? Ansi . Green : Ansi . Red ) + "r" ;
return output + $"{Ansi.ResetAll}]" ;
}
2023-01-22 02:08:24 +01:00
2023-01-23 17:52:01 +01:00
public static string TruncateString ( string input , int maxLen , string truncateMarker = "~" ) {
if ( maxLen < 2 )
maxLen = 2 ;
2023-01-23 17:55:50 +01:00
return input . Length < = maxLen ? input : input [ . . ( maxLen - 1 ) ] + truncateMarker ;
2023-01-23 17:52:01 +01:00
}
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
public static ( string messageBuffer , int relCursorPos ) GetPagedMessageInputLine ( string message , int absCursorPos , int bufferWidth ) {
const int wrapdOffsetPre = 2 ; // number of "untouchable" characters moving the cursor onto will cause a wrap on the right screen edge
const int wrapOffsetPost = 5 ; // number of "untouchable" characters moving the cursor onto will cause a wrap on the left screen edge
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
const int wrapOffsetPreI = wrapdOffsetPre + 1 ; // offset + 1 (indicator on the edge), for easier calculations
const int wrapOffsetPostI = wrapOffsetPost + 1 ; // offset + 1 (indicator on the edge), for easier calculations
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
if ( absCursorPos > message . Length )
throw new ArgumentOutOfRangeException ( nameof ( absCursorPos ) , "Cursor position exceeds message length" ) ;
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
if ( message . Length < bufferWidth ) // entire message fits in buffer
return ( message , absCursorPos ) ; // return input as-is
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
if ( absCursorPos < bufferWidth - wrapdOffsetPre - 1 ) // message is longer than buffer but we're on the first page
return ( TruncateString ( message , bufferWidth , $"{Ansi.Inverse}>{Ansi.InverseOff}" ) , absCursorPos ) ; // return input as-is but truncated and with a > indicator
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
var wraps = ( absCursorPos - wrapOffsetPostI ) / ( bufferWidth - wrapOffsetPreI - wrapOffsetPostI ) ; // black magic
var finalCursorPos = absCursorPos - bufferWidth + wrapOffsetPreI + wrapOffsetPostI * wraps ; // respect the special case of the first page & add one post offset per wrap
finalCursorPos % = bufferWidth - wrapOffsetPreI ; // make sure the final cursor position is within the acceptable range (between zero and bufWidth - wrapOffsetPreI)
2023-01-22 02:08:24 +01:00
2023-01-23 17:55:50 +01:00
var messageOffset = ( bufferWidth - wrapOffsetPreI - wrapOffsetPostI ) * wraps + 1 ; // +1 to account for the first wrap not having a < indicator
var finalMessage = message [ messageOffset . . ] ; // we only care about the message starting from the current page
2019-12-15 15:03:20 +01:00
2023-01-23 17:54:18 +01:00
finalMessage = TruncateString ( finalMessage , bufferWidth - 1 , $"{Ansi.Inverse}>{Ansi.InverseOff}" ) ; // replace the last character with a > indicator if required
2019-12-15 15:03:20 +01:00
2023-01-23 17:52:01 +01:00
return ( $"{Ansi.Inverse}<{Ansi.InverseOff}" + finalMessage , finalCursorPos ) ;
}
2019-12-21 23:45:23 +01:00
2023-01-23 17:52:01 +01:00
public static readonly List < Tuple < string , string > > Emojis = new ( ) {
new Tuple < string , string > ( "⏎ " , "\n" ) ,
new Tuple < string , string > ( ":xd:" , Emoji . FaceWithTearsOfJoy . Sequence . AsString ) ,
new Tuple < string , string > ( ":check:" , Emoji . CheckMark . Sequence . AsString ) ,
new Tuple < string , string > ( ":thinking:" , Emoji . ThinkingFace . Sequence . AsString ) ,
new Tuple < string , string > ( ":eyes:" , Emoji . Eyes . Sequence . AsString ) ,
new Tuple < string , string > ( ":heart:" , Emoji . RedHeart . Sequence . AsString ) ,
new Tuple < string , string > ( ":shrug:" , Emoji . PersonShrugging . Sequence . AsString ) ,
new Tuple < string , string > ( ":shrugf:" , Emoji . WomanShrugging . Sequence . AsString ) ,
new Tuple < string , string > ( ":shrugm:" , Emoji . ManShrugging . Sequence . AsString )
} ;
public static void InsertToInputLine ( string strToInsert ) {
2023-01-23 17:55:50 +01:00
var part1 = currentInputLine [ . . currentInputPos ] ;
var part2 = currentInputLine [ currentInputPos . . ] ;
2023-01-23 17:52:01 +01:00
currentInputLine = part1 + strToInsert + part2 ;
currentInputPos + = strToInsert . Length ;
}
2019-12-21 23:45:23 +01:00
2023-01-23 17:52:01 +01:00
public static void SetInputLine ( string newInputLine ) {
currentInputLine = newInputLine ;
currentInputPos = newInputLine . Length ;
}
2019-12-21 23:45:23 +01:00
2023-01-23 17:52:01 +01:00
public static void RemoveFromInputLine ( bool word = false ) {
2023-01-23 17:55:50 +01:00
var part1 = currentInputLine [ . . currentInputPos ] ;
2023-01-23 17:52:01 +01:00
var oldlen = part1 . Length ;
2023-01-23 17:55:50 +01:00
var part2 = currentInputLine [ currentInputPos . . ] ;
2023-01-23 17:52:01 +01:00
if ( word ) {
var lastIndex = part1 . TrimEnd ( ) . LastIndexOf ( " " , StringComparison . Ordinal ) ;
if ( lastIndex < 0 )
lastIndex = 0 ;
2023-01-23 17:55:50 +01:00
part1 = part1 [ . . lastIndex ] ;
2023-01-23 17:52:01 +01:00
if ( lastIndex ! = 0 )
part1 + = " " ;
//if (part1.EndsWith("⏎"))
// part1 = part1.Remove(part1.Length - 1);
var newlen = part1 . Length ;
currentInputLine = part1 + part2 ;
currentInputPos - = oldlen - newlen ;
return ;
}
2023-01-23 17:55:50 +01:00
currentInputLine = part1 [ . . ^ 1 ] + part2 ;
2023-01-23 17:52:01 +01:00
currentInputPos - - ;
}
2019-12-21 23:45:23 +01:00
2023-01-23 17:52:01 +01:00
public static void RemoveFromInputLineForward ( bool word = false ) {
2023-01-23 17:55:50 +01:00
var part1 = currentInputLine [ . . currentInputPos ] ;
var part2 = currentInputLine [ currentInputPos . . ] . TrimStart ( ) ;
2023-01-23 17:52:01 +01:00
if ( word ) {
var index = part2 . IndexOf ( " " , StringComparison . Ordinal ) ;
if ( index < 0 )
index = part2 . Length - 1 ;
2023-01-23 17:55:50 +01:00
part2 = part2 [ ( index + 1 ) . . ] ;
2023-01-23 17:52:01 +01:00
if ( index ! = 0 )
part2 = " " + part2 ;
//if (part2.StartsWith("⏎"))
// part2 = part2.Remove(part1.Length - 1);
2019-12-21 23:45:23 +01:00
2023-01-23 17:52:01 +01:00
currentInputLine = part1 + part2 ;
return ;
2019-12-21 23:45:23 +01:00
}
2023-01-23 17:55:50 +01:00
currentInputLine = part1 + part2 [ 1. . ] ;
2019-12-15 15:03:20 +01:00
}
2023-01-23 17:52:01 +01:00
public static readonly List < ConsoleKey > SpecialKeys = new ( ) {
ConsoleKey . Backspace ,
ConsoleKey . Tab ,
ConsoleKey . Clear ,
ConsoleKey . Enter ,
ConsoleKey . Pause ,
ConsoleKey . Escape ,
ConsoleKey . PageUp ,
ConsoleKey . PageDown ,
ConsoleKey . End ,
ConsoleKey . Home ,
ConsoleKey . LeftArrow ,
ConsoleKey . UpArrow ,
ConsoleKey . RightArrow ,
ConsoleKey . DownArrow ,
ConsoleKey . Select ,
ConsoleKey . Print ,
ConsoleKey . Execute ,
ConsoleKey . PrintScreen ,
ConsoleKey . Insert ,
ConsoleKey . Delete ,
ConsoleKey . Help ,
ConsoleKey . LeftWindows ,
ConsoleKey . RightWindows ,
ConsoleKey . Applications ,
ConsoleKey . Sleep ,
ConsoleKey . F1 ,
ConsoleKey . F2 ,
ConsoleKey . F3 ,
ConsoleKey . F4 ,
ConsoleKey . F5 ,
ConsoleKey . F6 ,
ConsoleKey . F7 ,
ConsoleKey . F8 ,
ConsoleKey . F9 ,
ConsoleKey . F10 ,
ConsoleKey . F11 ,
ConsoleKey . F12 ,
ConsoleKey . F13 ,
ConsoleKey . F14 ,
ConsoleKey . F15 ,
ConsoleKey . F16 ,
ConsoleKey . F17 ,
ConsoleKey . F18 ,
ConsoleKey . F19 ,
ConsoleKey . F20 ,
ConsoleKey . F21 ,
ConsoleKey . F22 ,
ConsoleKey . F23 ,
ConsoleKey . F24 ,
ConsoleKey . BrowserBack ,
ConsoleKey . BrowserForward ,
ConsoleKey . BrowserRefresh ,
ConsoleKey . BrowserStop ,
ConsoleKey . BrowserSearch ,
ConsoleKey . BrowserFavorites ,
ConsoleKey . BrowserHome ,
ConsoleKey . VolumeMute ,
ConsoleKey . VolumeDown ,
ConsoleKey . VolumeUp ,
ConsoleKey . MediaNext ,
ConsoleKey . MediaPrevious ,
ConsoleKey . MediaStop ,
ConsoleKey . MediaPlay ,
ConsoleKey . LaunchMail ,
ConsoleKey . LaunchMediaSelect ,
ConsoleKey . LaunchApp1 ,
ConsoleKey . LaunchApp2 ,
ConsoleKey . Oem1 ,
ConsoleKey . Oem2 ,
ConsoleKey . Oem3 ,
ConsoleKey . Oem4 ,
ConsoleKey . Oem5 ,
ConsoleKey . Oem6 ,
ConsoleKey . Oem7 ,
ConsoleKey . Oem8 ,
ConsoleKey . Oem102 ,
ConsoleKey . Process ,
ConsoleKey . Packet ,
ConsoleKey . Attention ,
ConsoleKey . CrSel ,
ConsoleKey . ExSel ,
ConsoleKey . EraseEndOfFile ,
ConsoleKey . Play ,
ConsoleKey . Zoom ,
ConsoleKey . NoName ,
ConsoleKey . Pa1 ,
ConsoleKey . OemClear
} ;
2023-01-14 04:32:36 +01:00
}