From fd69b673d872cbe3878b4c6b39f4d2bd73c8746f Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sun, 10 Apr 2022 12:18:53 +0100 Subject: [PATCH] terminal: use up arrow to edit the last message (#514) * terminal: use up error to edit the last message * update help --- src/Simplex/Chat.hs | 9 ++++++--- src/Simplex/Chat/Help.hs | 3 ++- src/Simplex/Chat/Terminal/Input.hs | 18 +++++++++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index e93abdede..c1f80c33f 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -146,10 +146,13 @@ withLock lock = (atomically $ putTMVar lock ()) execChatCommand :: (MonadUnliftIO m, MonadReader ChatController m) => ByteString -> m ChatResponse -execChatCommand s = case parseAll chatCommandP $ B.dropWhileEnd isSpace s of +execChatCommand s = case parseChatCommand s of Left e -> pure $ chatCmdError e Right cmd -> either CRChatCmdError id <$> runExceptT (processChatCommand cmd) +parseChatCommand :: ByteString -> Either String ChatCommand +parseChatCommand = parseAll chatCommandP . B.dropWhileEnd isSpace + toView :: ChatMonad m => ChatResponse -> m () toView event = do q <- asks outputQ @@ -1839,7 +1842,7 @@ chatCommandP = <|> (">#" <|> "> #") *> (SendGroupMessageQuote <$> displayName <* A.space <*> pure Nothing <*> quotedMsg <*> A.takeByteString) <|> (">#" <|> "> #") *> (SendGroupMessageQuote <$> displayName <* A.space <* optional (A.char '@') <*> (Just <$> displayName) <* A.space <*> quotedMsg <*> A.takeByteString) <|> ("\\#" <|> "\\ #") *> (DeleteGroupMessage <$> displayName <* A.space <*> A.takeByteString) - <|> ("!#" <|> "! #") *> (EditGroupMessage <$> displayName <* A.space <*> quotedMsg <*> A.takeByteString) + <|> ("!#" <|> "! #") *> (EditGroupMessage <$> displayName <* A.space <*> (quotedMsg <|> pure "") <*> A.takeByteString) <|> ("/contacts" <|> "/cs") $> ListContacts <|> ("/connect " <|> "/c ") *> (Connect <$> ((Just <$> strP) <|> A.takeByteString $> Nothing)) <|> ("/connect" <|> "/c") $> AddContact @@ -1848,7 +1851,7 @@ chatCommandP = <|> (">@" <|> "> @") *> sendMsgQuote (AMsgDirection SMDRcv) <|> (">>@" <|> ">> @") *> sendMsgQuote (AMsgDirection SMDSnd) <|> ("\\@" <|> "\\ @") *> (DeleteMessage <$> displayName <* A.space <*> A.takeByteString) - <|> ("!@" <|> "! @") *> (EditMessage <$> displayName <* A.space <*> quotedMsg <*> A.takeByteString) + <|> ("!@" <|> "! @") *> (EditMessage <$> displayName <* A.space <*> (quotedMsg <|> pure "") <*> A.takeByteString) <|> "/feed " *> (SendMessageBroadcast <$> A.takeByteString) <|> ("/file #" <|> "/f #") *> (SendGroupFile <$> displayName <* A.space <*> filePath) <|> ("/file_v2 #" <|> "/f_v2 #") *> (SendGroupFileInv <$> displayName <* A.space <*> filePath) diff --git a/src/Simplex/Chat/Help.hs b/src/Simplex/Chat/Help.hs index b3d1784eb..7725a7341 100644 --- a/src/Simplex/Chat/Help.hs +++ b/src/Simplex/Chat/Help.hs @@ -160,7 +160,8 @@ messagesHelpInfo = indent <> highlight "\\ #team hi " <> " - to delete your message in the group #team", "", green "Editing sent messages", - "To edit a message that starts with \"hi\":", + "To edit your last message press up arrow, edit (keep the initial ! symbol) and press enter.", + "To edit your most recent message that starts with \"hi\":", indent <> highlight "! @alice (hi) " <> " - to edit your message to alice", indent <> highlight "! #team (hi) " <> " - to edit your message in the group #team" ] diff --git a/src/Simplex/Chat/Terminal/Input.hs b/src/Simplex/Chat/Terminal/Input.hs index 6b215bd34..5e8f4bcd7 100644 --- a/src/Simplex/Chat/Terminal/Input.hs +++ b/src/Simplex/Chat/Terminal/Input.hs @@ -1,14 +1,14 @@ +{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Simplex.Chat.Terminal.Input where import Control.Monad.Except import Control.Monad.Reader -import qualified Data.ByteString.Char8 as B -import Data.Char (isSpace) import Data.List (dropWhileEnd) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) @@ -16,8 +16,8 @@ import Simplex.Chat import Simplex.Chat.Controller import Simplex.Chat.Styled import Simplex.Chat.Terminal.Output +import Simplex.Chat.Util (safeDecodeUtf8) import Simplex.Chat.View -import Simplex.Messaging.Parsers (parseAll) import System.Exit (exitSuccess) import System.Terminal hiding (insertChars) import UnliftIO.STM @@ -33,7 +33,7 @@ runInputLoop :: ChatTerminal -> ChatController -> IO () runInputLoop ct cc = forever $ do s <- atomically . readTBQueue $ inputQ cc let bs = encodeUtf8 $ T.pack s - cmd = parseAll chatCommandP $ B.dropWhileEnd isSpace bs + cmd = parseChatCommand bs unless (isMessage cmd) $ echo s r <- runReaderT (execChatCommand bs) cc case r of @@ -94,7 +94,7 @@ updateTermState ac tw (key, ms) ts@TerminalState {inputString = s, inputPosition Leftwards -> setPosition leftPos Rightwards -> setPosition rightPos Upwards - | ms == mempty && null s -> let s' = previousInput ts in ts' (s', length s') + | ms == mempty && null s -> let s' = upArrowCmd $ previousInput ts in ts' (s', length s') | ms == mempty -> let p' = p - tw in if p' > 0 then setPosition p' else ts | otherwise -> ts Downwards @@ -135,6 +135,14 @@ updateTermState ac tw (key, ms) ts@TerminalState {inputString = s, inputPosition | ms == ctrlKey = nextWordPos | ms == altKey = nextWordPos | otherwise = p + upArrowCmd inp = case parseChatCommand . encodeUtf8 $ T.pack inp of + Left _ -> inp + Right cmd -> case cmd of + SendMessage {} -> "! " <> inp + SendGroupMessage {} -> "! " <> inp + SendMessageQuote {contactName, message} -> T.unpack $ "! @" <> contactName <> " " <> safeDecodeUtf8 message + SendGroupMessageQuote {groupName, message} -> T.unpack $ "! #" <> groupName <> " " <> safeDecodeUtf8 message + _ -> inp setPosition p' = ts' (s, p') prevWordPos | p == 0 || null s = p