{-# LANGUAGE RankNTypes #-}
module Matterhorn.Draw.Autocomplete
  ( drawAutocompleteLayers
  )
where

import           Prelude ()
import           Matterhorn.Prelude

import           Brick
import           Brick.Widgets.Border
import           Brick.Widgets.List ( renderList, listElementsL, listSelectedFocusedAttr
                                    , listSelectedElement
                                    )
import qualified Data.Text as T
import           Lens.Micro.Platform ( SimpleGetter, Lens' )

import           Network.Mattermost.Types ( User(..), Channel(..), TeamId )

import           Matterhorn.Constants ( normalChannelSigil )
import           Matterhorn.Draw.Util ( mkChannelName )
import           Matterhorn.Themes
import           Matterhorn.Types
import           Matterhorn.Types.Common ( sanitizeUserText )

drawAutocompleteLayers :: ChatState -> [Widget Name]
drawAutocompleteLayers :: ChatState -> [Widget Name]
drawAutocompleteLayers ChatState
st =
    forall a. [Maybe a] -> [a]
catMaybes [ do
                    TeamId
tId <- ChatState
stforall s a. s -> Getting a s a -> a
^.SimpleGetter ChatState (Maybe TeamId)
csCurrentTeamId
                    ChannelId
cId <- ChatState
stforall s a. s -> Getting a s a -> a
^.TeamId -> SimpleGetter ChatState (Maybe ChannelId)
csCurrentChannelId(TeamId
tId)
                    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ChatState -> SimpleGetter ChatState (EditState Name) -> Widget Name
autocompleteLayer ChatState
st (ChannelId -> Lens' ChatState (EditState Name)
channelEditor(ChannelId
cId))
              , do
                    TeamId
tId <- ChatState
stforall s a. s -> Getting a s a -> a
^.SimpleGetter ChatState (Maybe TeamId)
csCurrentTeamId
                    forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ ChatState
stforall s a. s -> Getting a s a -> a
^.TeamId -> Lens' ChatState TeamState
csTeam(TeamId
tId)forall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' TeamState (Maybe ThreadInterface)
tsThreadInterface
                    let ti :: Lens' ChatState ThreadInterface
                        ti :: Lens' ChatState ThreadInterface
ti = HasCallStack => TeamId -> Lens' ChatState ThreadInterface
unsafeThreadInterface(TeamId
tId)
                        ed :: SimpleGetter ChatState (EditState Name)
                        ed :: SimpleGetter ChatState (EditState Name)
ed = Lens' ChatState ThreadInterface
tiforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall n i. Lens' (MessageInterface n i) (EditState n)
miEditor
                    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ChatState -> SimpleGetter ChatState (EditState Name) -> Widget Name
autocompleteLayer ChatState
st SimpleGetter ChatState (EditState Name)
ed
              ]

autocompleteLayer :: ChatState -> SimpleGetter ChatState (EditState Name) -> Widget Name
autocompleteLayer :: ChatState -> SimpleGetter ChatState (EditState Name) -> Widget Name
autocompleteLayer ChatState
st SimpleGetter ChatState (EditState Name)
which =
    case ChatState
stforall s a. s -> Getting a s a -> a
^.SimpleGetter ChatState (EditState Name)
whichforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall n. Lens' (EditState n) (Maybe (AutocompleteState n))
esAutocomplete of
        Maybe (AutocompleteState Name)
Nothing ->
            forall n. Widget n
emptyWidget
        Just AutocompleteState Name
ac ->
            forall a. a -> Maybe a -> a
fromMaybe forall n. Widget n
emptyWidget forall a b. (a -> b) -> a -> b
$ do
                TeamId
tId <- ChatState
stforall s a. s -> Getting a s a -> a
^.SimpleGetter ChatState (Maybe TeamId)
csCurrentTeamId
                let mcId :: Maybe ChannelId
mcId = ChatState
stforall s a. s -> Getting a s a -> a
^.TeamId -> SimpleGetter ChatState (Maybe ChannelId)
csCurrentChannelId(TeamId
tId)
                    mCurChan :: Maybe ClientChannel
mCurChan = do
                        ChannelId
cId <- Maybe ChannelId
mcId
                        ChatState
stforall s a. s -> Getting (First a) s a -> Maybe a
^?ChannelId -> Traversal' ChatState ClientChannel
csChannel(ChannelId
cId)
                forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ChatState
-> TeamId
-> Maybe ClientChannel
-> SimpleGetter ChatState (EditState Name)
-> AutocompleteState Name
-> Widget Name
renderAutocompleteBox ChatState
st TeamId
tId Maybe ClientChannel
mCurChan SimpleGetter ChatState (EditState Name)
which AutocompleteState Name
ac

userNotInChannelMarker :: T.Text
userNotInChannelMarker :: Text
userNotInChannelMarker = Text
"*"

elementTypeLabel :: AutocompletionType -> Text
elementTypeLabel :: AutocompletionType -> Text
elementTypeLabel AutocompletionType
ACUsers = Text
"Users"
elementTypeLabel AutocompletionType
ACChannels = Text
"Channels"
elementTypeLabel AutocompletionType
ACCodeBlockLanguage = Text
"Languages"
elementTypeLabel AutocompletionType
ACEmoji = Text
"Emoji"
elementTypeLabel AutocompletionType
ACCommands = Text
"Commands"

renderAutocompleteBox :: ChatState
                      -> TeamId
                      -> Maybe ClientChannel
                      -> SimpleGetter ChatState (EditState Name)
                      -> AutocompleteState Name
                      -> Widget Name
renderAutocompleteBox :: ChatState
-> TeamId
-> Maybe ClientChannel
-> SimpleGetter ChatState (EditState Name)
-> AutocompleteState Name
-> Widget Name
renderAutocompleteBox ChatState
st TeamId
tId Maybe ClientChannel
mCurChan SimpleGetter ChatState (EditState Name)
which AutocompleteState Name
ac =
    let matchList :: List Name AutocompleteAlternative
matchList = forall n. AutocompleteState n -> List n AutocompleteAlternative
_acCompletionList AutocompleteState Name
ac
        maxListHeight :: Int
maxListHeight = Int
5
        visibleHeight :: Int
visibleHeight = forall a. Ord a => a -> a -> a
min Int
maxListHeight Int
numResults
        numResults :: Int
numResults = forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector AutocompleteAlternative
elements
        elements :: Vector AutocompleteAlternative
elements = List Name AutocompleteAlternative
matchListforall s a. s -> Getting a s a -> a
^.forall n (t1 :: * -> *) e1 (t2 :: * -> *) e2.
Lens (GenericList n t1 e1) (GenericList n t2 e2) (t1 e1) (t2 e2)
listElementsL
        editorName :: Name
editorName = forall a n. Named a n => a -> n
getName forall a b. (a -> b) -> a -> b
$ ChatState
stforall s a. s -> Getting a s a -> a
^.SimpleGetter ChatState (EditState Name)
whichforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall n. Lens' (EditState n) (Editor Text n)
esEditor
        isMultiline :: Bool
isMultiline = ChatState
stforall s a. s -> Getting a s a -> a
^.SimpleGetter ChatState (EditState Name)
whichforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall n. Lens' (EditState n) EphemeralEditState
esEphemeralforall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' EphemeralEditState Bool
eesMultiline
        label :: Widget n
label = forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientMessageAttr forall a b. (a -> b) -> a -> b
$
                forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ AutocompletionType -> Text
elementTypeLabel (AutocompleteState Name
acforall s a. s -> Getting a s a -> a
^.forall n. Lens' (AutocompleteState n) AutocompletionType
acType) forall a. Semigroup a => a -> a -> a
<> Text
": " forall a. Semigroup a => a -> a -> a
<> (String -> Text
T.pack forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int
numResults) forall a. Semigroup a => a -> a -> a
<>
                     Text
" match" forall a. Semigroup a => a -> a -> a
<> (if Int
numResults forall a. Eq a => a -> a -> Bool
== Int
1 then Text
"" else Text
"es") forall a. Semigroup a => a -> a -> a
<>
                     Text
" (Tab/Shift-Tab to select)"

        selElem :: Maybe AutocompleteAlternative
selElem = forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) e n.
(Splittable t, Traversable t, Semigroup (t e)) =>
GenericList n t e -> Maybe (Int, e)
listSelectedElement List Name AutocompleteAlternative
matchList
        footer :: Widget Name
footer = case Maybe ClientChannel
mCurChan of
            Maybe ClientChannel
Nothing ->
                forall n. Widget n
hBorder
            Just ClientChannel
curChan ->
                case ChatState
-> ClientChannel -> AutocompleteAlternative -> Maybe (Widget Name)
renderAutocompleteFooterFor ChatState
st ClientChannel
curChan forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe AutocompleteAlternative
selElem of
                    Just Widget Name
w -> forall n. Widget n -> Widget n
hBorderWithLabel Widget Name
w
                    Maybe (Widget Name)
_ -> forall n. Widget n
hBorder
        curUser :: Text
curUser = ChatState -> Text
myUsername ChatState
st
        cfg :: Config
cfg = ChatState
stforall s a. s -> Getting a s a -> a
^.Lens' ChatState ChatResources
csResourcesforall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' ChatResources Config
crConfiguration
        showingChanList :: Bool
showingChanList = Config -> Bool
configShowChannelList Config
cfg
        chanListWidth :: Int
chanListWidth = Config -> Int
configChannelListWidth Config
cfg
        maybeLimit :: Widget n -> Widget n
maybeLimit = forall a. a -> Maybe a -> a
fromMaybe forall a. a -> a
id forall a b. (a -> b) -> a -> b
$ do
            let sub :: Int
sub = if Bool
showingChanList
                      then Int
chanListWidth forall a. Num a => a -> a -> a
+ Int
1
                      else Int
0
                threadNarrow :: Bool
threadNarrow = Bool
threadShowing Bool -> Bool -> Bool
&& (Config
cfgforall s a. s -> Getting a s a -> a
^.Lens' Config ThreadOrientation
configThreadOrientationL forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ThreadOrientation
ThreadLeft, ThreadOrientation
ThreadRight])
                threadShowing :: Bool
threadShowing = forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ ChatState
stforall s a. s -> Getting a s a -> a
^.TeamId -> Lens' ChatState TeamState
csTeam(TeamId
tId)forall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' TeamState (Maybe ThreadInterface)
tsThreadInterface

            if Bool
threadNarrow Bool -> Bool -> Bool
|| Int
sub forall a. Ord a => a -> a -> Bool
> Int
0
               then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ \Widget n
w -> forall n. Size -> Size -> RenderM n (Result n) -> Widget n
Widget Size
Greedy Size
Greedy forall a b. (a -> b) -> a -> b
$ do
                   Context n
ctx <- forall n. RenderM n (Context n)
getContext
                   let adjusted :: Int
adjusted = Context n
ctxforall s a. s -> Getting a s a -> a
^.forall n. Lens' (Context n) Int
availWidthL forall a. Num a => a -> a -> a
- Int
sub
                       lim :: Int
lim = if Bool
threadNarrow
                             then (Int
adjusted forall a. Num a => a -> a -> a
- Int
1) forall a. Integral a => a -> a -> a
`div` Int
2
                             else Int
adjusted
                   forall n. Widget n -> RenderM n (Result n)
render forall a b. (a -> b) -> a -> b
$ forall n. Int -> Widget n -> Widget n
hLimit Int
lim Widget n
w
               else forall a. Maybe a
Nothing

        -- The top left corner of the editor area is given by the
        -- prompt, or by the editor position if multiline is enabled (in
        -- which case no prompt is drawn).
        editorTop :: Name
editorTop = if Bool
isMultiline
                    then Name
editorName
                    else Name -> Name
MessageInputPrompt Name
editorName

    in if Int
numResults forall a. Eq a => a -> a -> Bool
== Int
0
       then forall n. Widget n
emptyWidget
       else forall n. Size -> Size -> RenderM n (Result n) -> Widget n
Widget Size
Greedy Size
Greedy forall a b. (a -> b) -> a -> b
$ do
           let verticalOffset :: Int
verticalOffset = -Int
1 forall a. Num a => a -> a -> a
* (Int
visibleHeight forall a. Num a => a -> a -> a
+ Int
2)
           forall n. Widget n -> RenderM n (Result n)
render forall a b. (a -> b) -> a -> b
$ forall n. Ord n => n -> Location -> Widget n -> Widget n
relativeTo Name
editorTop ((Int, Int) -> Location
Location (Int
0, Int
verticalOffset)) forall a b. (a -> b) -> a -> b
$
                    forall n. Widget n -> Widget n
maybeLimit forall a b. (a -> b) -> a -> b
$
                    forall n. [Widget n] -> Widget n
vBox [ forall n. Widget n -> Widget n
hBorderWithLabel forall n. Widget n
label
                         , forall n. Int -> Widget n -> Widget n
vLimit Int
visibleHeight forall a b. (a -> b) -> a -> b
$
                           forall (t :: * -> *) n e.
(Traversable t, Splittable t, Ord n, Show n) =>
(Bool -> e -> Widget n) -> Bool -> GenericList n t e -> Widget n
renderList (Text -> Bool -> AutocompleteAlternative -> Widget Name
renderAutocompleteAlternative Text
curUser) Bool
True List Name AutocompleteAlternative
matchList
                         , Widget Name
footer
                         ]

renderAutocompleteFooterFor :: ChatState -> ClientChannel -> AutocompleteAlternative -> Maybe (Widget Name)
renderAutocompleteFooterFor :: ChatState
-> ClientChannel -> AutocompleteAlternative -> Maybe (Widget Name)
renderAutocompleteFooterFor ChatState
_ ClientChannel
_ (SpecialMention SpecialMention
MentionChannel) = forall a. Maybe a
Nothing
renderAutocompleteFooterFor ChatState
_ ClientChannel
_ (SpecialMention SpecialMention
MentionAll) = forall a. Maybe a
Nothing
renderAutocompleteFooterFor ChatState
st ClientChannel
ch (UserCompletion User
_ Bool
False) =
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall n. [Widget n] -> Widget n
hBox [ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"("
                , forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientEmphAttr (forall n. Text -> Widget n
txt Text
userNotInChannelMarker)
                , forall n. Text -> Widget n
txt Text
": not a member of "
                , forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
channelNameAttr (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ ChatState -> ChannelInfo -> Text
mkChannelName ChatState
st (ClientChannel
chforall s a. s -> Getting a s a -> a
^.Lens' ClientChannel ChannelInfo
ccInfo))
                , forall n. Text -> Widget n
txt Text
")"
                ]
renderAutocompleteFooterFor ChatState
_ ClientChannel
_ (ChannelCompletion Bool
False Channel
ch) =
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall n. [Widget n] -> Widget n
hBox [ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"("
                , forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientEmphAttr (forall n. Text -> Widget n
txt Text
userNotInChannelMarker)
                , forall n. Text -> Widget n
txt Text
": you are not a member of "
                , forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
channelNameAttr (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
normalChannelSigil forall a. Semigroup a => a -> a -> a
<> Channel -> Text
preferredChannelName Channel
ch)
                , forall n. Text -> Widget n
txt Text
")"
                ]
renderAutocompleteFooterFor ChatState
_ ClientChannel
_ (CommandCompletion CompletionSource
src Text
_ Text
_ Text
_) =
    case CompletionSource
src of
        CompletionSource
Server ->
            forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall n. [Widget n] -> Widget n
hBox [ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"("
                        , forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientEmphAttr (forall n. Text -> Widget n
txt Text
serverCommandMarker)
                        , forall n. Text -> Widget n
txt Text
": command provided by the server)"
                        ]
        CompletionSource
Client -> forall a. Maybe a
Nothing
renderAutocompleteFooterFor ChatState
_ ClientChannel
_ AutocompleteAlternative
_ =
    forall a. Maybe a
Nothing

serverCommandMarker :: Text
serverCommandMarker :: Text
serverCommandMarker = Text
"*"

renderAutocompleteAlternative :: Text -> Bool -> AutocompleteAlternative -> Widget Name
renderAutocompleteAlternative :: Text -> Bool -> AutocompleteAlternative -> Widget Name
renderAutocompleteAlternative Text
_ Bool
sel (EmojiCompletion Text
e) =
    forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ Bool -> Text -> Widget Name
renderEmojiCompletion Bool
sel Text
e
renderAutocompleteAlternative Text
_ Bool
sel (SpecialMention SpecialMention
m) =
    forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ SpecialMention -> Bool -> Widget Name
renderSpecialMention SpecialMention
m Bool
sel
renderAutocompleteAlternative Text
curUser Bool
sel (UserCompletion User
u Bool
inChan) =
    forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ Text -> User -> Bool -> Bool -> Widget Name
renderUserCompletion Text
curUser User
u Bool
inChan Bool
sel
renderAutocompleteAlternative Text
_ Bool
sel (ChannelCompletion Bool
inChan Channel
c) =
    forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ Channel -> Bool -> Bool -> Widget Name
renderChannelCompletion Channel
c Bool
inChan Bool
sel
renderAutocompleteAlternative Text
_ Bool
_ (SyntaxCompletion Text
t) =
    forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
t
renderAutocompleteAlternative Text
_ Bool
_ (CommandCompletion CompletionSource
src Text
n Text
args Text
desc) =
    forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ CompletionSource -> Text -> Text -> Text -> Widget Name
renderCommandCompletion CompletionSource
src Text
n Text
args Text
desc

renderSpecialMention :: SpecialMention -> Bool -> Widget Name
renderSpecialMention :: SpecialMention -> Bool -> Widget Name
renderSpecialMention SpecialMention
m Bool
sel =
    let usernameWidth :: Int
usernameWidth = Int
18
        padTo :: Int -> Widget n -> Widget n
padTo Int
n Widget n
a = forall n. Int -> Widget n -> Widget n
hLimit Int
n forall a b. (a -> b) -> a -> b
$ forall n. Int -> Widget n -> Widget n
vLimit Int
1 (Widget n
a forall n. Widget n -> Widget n -> Widget n
<+> forall n. Char -> Widget n
fill Char
' ')
        maybeForce :: Widget n -> Widget n
maybeForce = if Bool
sel
                     then forall n. AttrName -> Widget n -> Widget n
forceAttr AttrName
listSelectedFocusedAttr
                     else forall a. a -> a
id
        t :: Text
t = AutocompleteAlternative -> Text
autocompleteAlternativeReplacement forall a b. (a -> b) -> a -> b
$ SpecialMention -> AutocompleteAlternative
SpecialMention SpecialMention
m
        desc :: Text
desc = case SpecialMention
m of
            SpecialMention
MentionChannel -> Text
"Notifies all users in this channel"
            SpecialMention
MentionAll     -> Text
"Mentions all users in this channel"
    in forall n. Widget n -> Widget n
maybeForce forall a b. (a -> b) -> a -> b
$
       forall n. [Widget n] -> Widget n
hBox [ forall n. Text -> Widget n
txt Text
"  "
            , forall n. Int -> Widget n -> Widget n
padTo Int
usernameWidth forall a b. (a -> b) -> a -> b
$ forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientEmphAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
t
            , forall n. Text -> Widget n
txt Text
desc
            ]

renderEmojiCompletion :: Bool -> T.Text -> Widget Name
renderEmojiCompletion :: Bool -> Text -> Widget Name
renderEmojiCompletion Bool
sel Text
e =
    let maybeForce :: Widget n -> Widget n
maybeForce = if Bool
sel
                     then forall n. AttrName -> Widget n -> Widget n
forceAttr AttrName
listSelectedFocusedAttr
                     else forall a. a -> a
id
    in forall n. Widget n -> Widget n
maybeForce forall a b. (a -> b) -> a -> b
$
       forall n. Padding -> Widget n -> Widget n
padLeft (Int -> Padding
Pad Int
2) forall a b. (a -> b) -> a -> b
$
       forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
emojiAttr forall a b. (a -> b) -> a -> b
$
       forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$
       AutocompleteAlternative -> Text
autocompleteAlternativeReplacement forall a b. (a -> b) -> a -> b
$ Text -> AutocompleteAlternative
EmojiCompletion Text
e

renderUserCompletion :: Text -> User -> Bool -> Bool -> Widget Name
renderUserCompletion :: Text -> User -> Bool -> Bool -> Widget Name
renderUserCompletion Text
curUser User
u Bool
inChan Bool
selected =
    let usernameWidth :: Int
usernameWidth = Int
18
        fullNameWidth :: Int
fullNameWidth = Int
25
        padTo :: Int -> Widget n -> Widget n
padTo Int
n Widget n
a = forall n. Int -> Widget n -> Widget n
hLimit Int
n forall a b. (a -> b) -> a -> b
$ forall n. Int -> Widget n -> Widget n
vLimit Int
1 (Widget n
a forall n. Widget n -> Widget n -> Widget n
<+> forall n. Char -> Widget n
fill Char
' ')
        username :: Text
username = User -> Text
userUsername User
u
        fullName :: Text
fullName = (UserText -> Text
sanitizeUserText forall a b. (a -> b) -> a -> b
$ User -> UserText
userFirstName User
u) forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<>
                   (UserText -> Text
sanitizeUserText forall a b. (a -> b) -> a -> b
$ User -> UserText
userLastName User
u)
        nickname :: Text
nickname = UserText -> Text
sanitizeUserText forall a b. (a -> b) -> a -> b
$ User -> UserText
userNickname User
u
        maybeForce :: Widget n -> Widget n
maybeForce = if Bool
selected
                     then forall n. AttrName -> Widget n -> Widget n
forceAttr AttrName
listSelectedFocusedAttr
                     else forall a. a -> a
id
        memberDisplay :: Widget n
memberDisplay = if Bool
inChan
                        then forall n. Text -> Widget n
txt Text
"  "
                        else forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientEmphAttr forall a b. (a -> b) -> a -> b
$
                             forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
userNotInChannelMarker forall a. Semigroup a => a -> a -> a
<> Text
" "
    in forall n. Widget n -> Widget n
maybeForce forall a b. (a -> b) -> a -> b
$
       forall n. [Widget n] -> Widget n
hBox [ forall n. Widget n
memberDisplay
            , forall n. Int -> Widget n -> Widget n
padTo Int
usernameWidth forall a b. (a -> b) -> a -> b
$ forall a. Text -> Text -> Text -> Widget a
colorUsername Text
curUser Text
username (Text
"@" forall a. Semigroup a => a -> a -> a
<> Text
username)
            , forall n. Int -> Widget n -> Widget n
padTo Int
fullNameWidth forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
fullName
            , forall n. Text -> Widget n
txt Text
nickname
            ]

renderChannelCompletion :: Channel -> Bool -> Bool -> Widget Name
renderChannelCompletion :: Channel -> Bool -> Bool -> Widget Name
renderChannelCompletion Channel
c Bool
inChan Bool
selected =
    let urlNameWidth :: Int
urlNameWidth = Int
30
        displayNameWidth :: Int
displayNameWidth = Int
30
        padTo :: Int -> Widget n -> Widget n
padTo Int
n Widget n
a = forall n. Int -> Widget n -> Widget n
hLimit Int
n forall a b. (a -> b) -> a -> b
$ forall n. Int -> Widget n -> Widget n
vLimit Int
1 (Widget n
a forall n. Widget n -> Widget n -> Widget n
<+> forall n. Char -> Widget n
fill Char
' ')
        maybeForce :: Widget n -> Widget n
maybeForce = if Bool
selected
                     then forall n. AttrName -> Widget n -> Widget n
forceAttr AttrName
listSelectedFocusedAttr
                     else forall a. a -> a
id
        memberDisplay :: Widget n
memberDisplay = if Bool
inChan
                        then forall n. Text -> Widget n
txt Text
"  "
                        else forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientEmphAttr forall a b. (a -> b) -> a -> b
$
                             forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
userNotInChannelMarker forall a. Semigroup a => a -> a -> a
<> Text
" "
    in forall n. Widget n -> Widget n
maybeForce forall a b. (a -> b) -> a -> b
$
       forall n. [Widget n] -> Widget n
hBox [ forall n. Widget n
memberDisplay
            , forall n. Int -> Widget n -> Widget n
padTo Int
urlNameWidth forall a b. (a -> b) -> a -> b
$
              forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
channelNameAttr forall a b. (a -> b) -> a -> b
$
              forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
normalChannelSigil forall a. Semigroup a => a -> a -> a
<> (UserText -> Text
sanitizeUserText forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelName Channel
c)
            , forall n. Int -> Widget n -> Widget n
padTo Int
displayNameWidth forall a b. (a -> b) -> a -> b
$
              forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
channelNameAttr forall a b. (a -> b) -> a -> b
$
              forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ UserText -> Text
sanitizeUserText forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelDisplayName Channel
c
            , forall n. Int -> Widget n -> Widget n
vLimit Int
1 forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ UserText -> Text
sanitizeUserText forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelPurpose Channel
c
            ]

renderCommandCompletion :: CompletionSource -> Text -> Text -> Text -> Widget Name
renderCommandCompletion :: CompletionSource -> Text -> Text -> Text -> Widget Name
renderCommandCompletion CompletionSource
src Text
name Text
args Text
desc =
    (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
" " forall a. Semigroup a => a -> a -> a
<> Text
srcTxt forall a. Semigroup a => a -> a -> a
<> Text
" ") forall n. Widget n -> Widget n -> Widget n
<+>
    forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
clientMessageAttr
        (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"/" forall a. Semigroup a => a -> a -> a
<> Text
name forall a. Semigroup a => a -> a -> a
<> if Text -> Bool
T.null Text
args then Text
"" else Text
" " forall a. Semigroup a => a -> a -> a
<> Text
args) forall n. Widget n -> Widget n -> Widget n
<+>
    (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
" - " forall a. Semigroup a => a -> a -> a
<> Text
desc)
    where
        srcTxt :: Text
srcTxt = case CompletionSource
src of
            CompletionSource
Server -> Text
serverCommandMarker
            CompletionSource
Client -> Text
" "