matterhorn-50200.2.0: src/Events/Main.hs
{-# LANGUAGE MultiWayIf #-}
module Events.Main where
import Prelude ()
import Prelude.MH
import Brick.Widgets.Edit
import qualified Brick.Widgets.List as L
import Data.Char ( isSpace )
import qualified Data.Text.Zipper as Z
import qualified Data.Text.Zipper.Generic.Words as Z
import qualified Graphics.Vty as Vty
import Lens.Micro.Platform ( (%=), to, _Just )
import Command
import Events.Keybindings
import HelpTopics ( mainHelpTopic )
import State.Attachments
import State.ChannelSelect
import State.Channels
import State.Editing
import State.Help
import State.MessageSelect
import State.PostListOverlay ( enterFlaggedPostListMode )
import State.UrlSelect
import Types
onEventMain :: Vty.Event -> MH ()
onEventMain =
handleKeyboardEvent mainKeybindings $ \ ev -> case ev of
(Vty.EvPaste bytes) -> handlePaste bytes
_ -> handleEditingInput ev
mainKeybindings :: KeyConfig -> [Keybinding]
mainKeybindings = mkKeybindings
[ mkKb ShowHelpEvent
"Show this help screen"
(showHelpScreen mainHelpTopic)
, mkKb EnterSelectModeEvent
"Select a message to edit/reply/delete"
beginMessageSelect
, mkKb ReplyRecentEvent
"Reply to the most recent message"
replyToLatestMessage
, mkKb ToggleMessagePreviewEvent "Toggle message preview"
toggleMessagePreview
, mkKb ToggleChannelListVisibleEvent "Toggle channel list visibility"
toggleChannelListVisibility
, mkKb
InvokeEditorEvent
"Invoke *$EDITOR* to edit the current message"
invokeExternalEditor
, mkKb
EnterFastSelectModeEvent
"Enter fast channel selection mode"
beginChannelSelect
, mkKb
QuitEvent
"Quit"
requestQuit
, staticKb "Tab-complete forward"
(Vty.EvKey (Vty.KChar '\t') []) $
tabComplete Forwards
, staticKb "Tab-complete backward"
(Vty.EvKey (Vty.KBackTab) []) $
tabComplete Backwards
, mkKb
ScrollUpEvent
"Scroll up in the channel input history" $ do
-- Up in multiline mode does the usual thing; otherwise we
-- navigate the history.
isMultiline <- use (csEditState.cedEphemeral.eesMultiline)
case isMultiline of
True -> mhHandleEventLensed (csEditState.cedEditor) handleEditorEvent
(Vty.EvKey Vty.KUp [])
False -> channelHistoryBackward
, mkKb
ScrollDownEvent
"Scroll down in the channel input history" $ do
-- Down in multiline mode does the usual thing; otherwise
-- we navigate the history.
isMultiline <- use (csEditState.cedEphemeral.eesMultiline)
case isMultiline of
True -> mhHandleEventLensed (csEditState.cedEditor) handleEditorEvent
(Vty.EvKey Vty.KDown [])
False -> channelHistoryForward
, mkKb PageUpEvent "Page up in the channel message list (enters message select mode)" $ do
beginMessageSelect
, mkKb ScrollTopEvent "Scroll to top of channel message list" $ do
beginMessageSelect
messageSelectFirst
, mkKb NextChannelEvent "Change to the next channel in the channel list"
nextChannel
, mkKb PrevChannelEvent "Change to the previous channel in the channel list"
prevChannel
, mkKb NextUnreadChannelEvent "Change to the next channel with unread messages"
nextUnreadChannel
, mkKb ShowAttachmentListEvent "Show the attachment list"
showAttachmentList
, mkKb NextUnreadUserOrChannelEvent
"Change to the next channel with unread messages preferring direct messages"
nextUnreadUserOrChannel
, mkKb LastChannelEvent "Change to the most recently-focused channel"
recentChannel
, staticKb "Send the current message"
(Vty.EvKey Vty.KEnter []) $ do
isMultiline <- use (csEditState.cedEphemeral.eesMultiline)
case isMultiline of
-- Normally, this event causes the current message to
-- be sent. But in multiline mode we want to insert a
-- newline instead.
True -> handleEditingInput (Vty.EvKey Vty.KEnter [])
False -> do
cId <- use csCurrentChannelId
content <- getEditorContent
handleInputSubmission cId content
, mkKb EnterOpenURLModeEvent "Select and open a URL posted to the current channel"
startUrlSelect
, mkKb ClearUnreadEvent "Clear the current channel's unread / edited indicators" $
clearChannelUnreadStatus =<< use csCurrentChannelId
, mkKb ToggleMultiLineEvent "Toggle multi-line message compose mode"
toggleMultilineEditing
, mkKb CancelEvent "Cancel autocomplete, message reply, or edit, in that order"
cancelAutocompleteOrReplyOrEdit
, mkKb EnterFlaggedPostsEvent "View currently flagged posts"
enterFlaggedPostListMode
]
data Direction = Forwards | Backwards
tabComplete :: Direction -> MH ()
tabComplete dir = do
let transform list =
let len = list^.L.listElementsL.to length
in case dir of
Forwards ->
if (L.listSelected list == Just (len - 1)) ||
(L.listSelected list == Nothing && len > 0)
then L.listMoveTo 0 list
else L.listMoveBy 1 list
Backwards ->
if (L.listSelected list == Just 0) ||
(L.listSelected list == Nothing && len > 0)
then L.listMoveTo (len - 1) list
else L.listMoveBy (-1) list
csEditState.cedAutocomplete._Just.acCompletionList %= transform
mac <- use (csEditState.cedAutocomplete)
case mac of
Nothing -> return ()
Just ac -> do
case ac^.acCompletionList.to L.listSelectedElement of
Nothing -> return ()
Just (_, alternative) -> do
let replacement = autocompleteAlternativeReplacement alternative
maybeEndOfWord z =
if maybe True isSpace (Z.currentChar z)
then z
else Z.moveWordRight z
csEditState.cedEditor %=
applyEdit (Z.insertMany replacement . Z.deletePrevWord .
maybeEndOfWord)