{-# LANGUAGE RankNTypes #-}
module Matterhorn.State.Autocomplete
( AutocompleteContext(..)
, checkForAutocompletion
)
where
import Prelude ()
import Matterhorn.Prelude
import Brick ( getName )
import Brick.Main ( viewportScroll, vScrollToBeginning )
import Brick.Widgets.Edit ( editContentsL )
import qualified Brick.Widgets.List as L
import Data.Char ( isSpace )
import qualified Data.Foldable as F
import qualified Data.HashMap.Strict as HM
import Data.List ( sortBy, partition )
import qualified Data.Map as M
import Data.Maybe ( fromJust )
import qualified Data.Sequence as Seq
import qualified Data.Text as T
import qualified Data.Text.Zipper as Z
import qualified Data.Vector as V
import Lens.Micro.Platform ( (%=), (.=), (.~), _Just, Traversal' )
import qualified Skylighting.Types as Sky
import Network.Mattermost.Types (userId, channelId, Command(..), TeamId)
import qualified Network.Mattermost.Endpoints as MM
import Matterhorn.Constants ( userSigil, normalChannelSigil )
import {-# SOURCE #-} Matterhorn.Command ( commandList, printArgSpec )
import Matterhorn.State.Common
import {-# SOURCE #-} Matterhorn.State.Editing ( Direction(..), tabComplete )
import Matterhorn.Types hiding ( newState )
import Matterhorn.Emoji
data AutocompleteContext =
AutocompleteContext { AutocompleteContext -> Bool
autocompleteManual :: Bool
, AutocompleteContext -> Bool
autocompleteFirstMatch :: Bool
}
checkForAutocompletion :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> MH ()
checkForAutocompletion :: Traversal' ChatState (EditState Name)
-> AutocompleteContext -> MH ()
checkForAutocompletion Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx = do
Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
result <- Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> MH
(Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text))
getCompleterForInput (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx
case Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
result of
Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
Nothing -> Traversal' ChatState (EditState Name) -> MH ()
forall n. Traversal' ChatState (EditState n) -> MH ()
resetAutocomplete (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which
Just (AutocompletionType
ty, AutocompletionType -> AutocompleteContext -> Text -> MH ()
runUpdater, Text
searchString) -> do
Maybe (AutocompleteState Name)
prevResult <- Maybe (Maybe (AutocompleteState Name))
-> Maybe (AutocompleteState Name)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe (AutocompleteState Name))
-> Maybe (AutocompleteState Name))
-> MH (Maybe (Maybe (AutocompleteState Name)))
-> MH (Maybe (AutocompleteState Name))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting
(First (Maybe (AutocompleteState Name)))
ChatState
(Maybe (AutocompleteState Name))
-> MH (Maybe (Maybe (AutocompleteState Name)))
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name
-> Const (First (Maybe (AutocompleteState Name))) (EditState Name))
-> ChatState
-> Const (First (Maybe (AutocompleteState Name))) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name
-> Const (First (Maybe (AutocompleteState Name))) (EditState Name))
-> ChatState
-> Const (First (Maybe (AutocompleteState Name))) ChatState)
-> ((Maybe (AutocompleteState Name)
-> Const
(First (Maybe (AutocompleteState Name)))
(Maybe (AutocompleteState Name)))
-> EditState Name
-> Const (First (Maybe (AutocompleteState Name))) (EditState Name))
-> Getting
(First (Maybe (AutocompleteState Name)))
ChatState
(Maybe (AutocompleteState Name))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (AutocompleteState Name)
-> Const
(First (Maybe (AutocompleteState Name)))
(Maybe (AutocompleteState Name)))
-> EditState Name
-> Const (First (Maybe (AutocompleteState Name))) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe (AutocompleteState n) -> f (Maybe (AutocompleteState n)))
-> EditState n -> f (EditState n)
esAutocomplete)
let shouldUpdate :: Bool
shouldUpdate = ((Bool
-> (AutocompleteState Name -> Bool)
-> Maybe (AutocompleteState Name)
-> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True ((Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
searchString) (Text -> Bool)
-> (AutocompleteState Name -> Text)
-> AutocompleteState Name
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AutocompleteState Name -> Text
forall n. AutocompleteState n -> Text
_acPreviousSearchString)
Maybe (AutocompleteState Name)
prevResult) Bool -> Bool -> Bool
&&
(Bool
-> (AutocompleteState Name -> Bool)
-> Maybe (AutocompleteState Name)
-> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True ((AutocompletionType -> AutocompletionType -> Bool
forall a. Eq a => a -> a -> Bool
== AutocompletionType
ty) (AutocompletionType -> Bool)
-> (AutocompleteState Name -> AutocompletionType)
-> AutocompleteState Name
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AutocompleteState Name -> AutocompletionType
forall n. AutocompleteState n -> AutocompletionType
_acType) Maybe (AutocompleteState Name)
prevResult)) Bool -> Bool -> Bool
||
(Bool
-> (AutocompleteState Name -> Bool)
-> Maybe (AutocompleteState Name)
-> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False ((AutocompletionType -> AutocompletionType -> Bool
forall a. Eq a => a -> a -> Bool
/= AutocompletionType
ty) (AutocompletionType -> Bool)
-> (AutocompleteState Name -> AutocompletionType)
-> AutocompleteState Name
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AutocompleteState Name -> AutocompletionType
forall n. AutocompleteState n -> AutocompletionType
_acType) Maybe (AutocompleteState Name)
prevResult)
Bool -> MH () -> MH ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
shouldUpdate (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$ do
(EditState Name -> Identity (EditState Name))
-> ChatState -> Identity ChatState
Traversal' ChatState (EditState Name)
which((EditState Name -> Identity (EditState Name))
-> ChatState -> Identity ChatState)
-> ((Maybe Text -> Identity (Maybe Text))
-> EditState Name -> Identity (EditState Name))
-> (Maybe Text -> Identity (Maybe Text))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe Text -> Identity (Maybe Text))
-> EditState Name -> Identity (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe Text -> f (Maybe Text)) -> EditState n -> f (EditState n)
esAutocompletePending ((Maybe Text -> Identity (Maybe Text))
-> ChatState -> Identity ChatState)
-> Maybe Text -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Text -> Maybe Text
forall a. a -> Maybe a
Just Text
searchString
AutocompletionType -> AutocompleteContext -> Text -> MH ()
runUpdater AutocompletionType
ty AutocompleteContext
ctx Text
searchString
getCompleterForInput :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> MH (Maybe (AutocompletionType, AutocompletionType -> AutocompleteContext -> Text -> MH (), Text))
getCompleterForInput :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> MH
(Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text))
getCompleterForInput Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx = do
Maybe (TextZipper Text)
maybeZipper <- Getting (First (TextZipper Text)) ChatState (TextZipper Text)
-> MH (Maybe (TextZipper Text))
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name
-> Const (First (TextZipper Text)) (EditState Name))
-> ChatState -> Const (First (TextZipper Text)) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name
-> Const (First (TextZipper Text)) (EditState Name))
-> ChatState -> Const (First (TextZipper Text)) ChatState)
-> ((TextZipper Text
-> Const (First (TextZipper Text)) (TextZipper Text))
-> EditState Name
-> Const (First (TextZipper Text)) (EditState Name))
-> Getting (First (TextZipper Text)) ChatState (TextZipper Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Editor Text Name
-> Const (First (TextZipper Text)) (Editor Text Name))
-> EditState Name
-> Const (First (TextZipper Text)) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> EditState n -> f (EditState n)
esEditor((Editor Text Name
-> Const (First (TextZipper Text)) (Editor Text Name))
-> EditState Name
-> Const (First (TextZipper Text)) (EditState Name))
-> ((TextZipper Text
-> Const (First (TextZipper Text)) (TextZipper Text))
-> Editor Text Name
-> Const (First (TextZipper Text)) (Editor Text Name))
-> (TextZipper Text
-> Const (First (TextZipper Text)) (TextZipper Text))
-> EditState Name
-> Const (First (TextZipper Text)) (EditState Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(TextZipper Text
-> Const (First (TextZipper Text)) (TextZipper Text))
-> Editor Text Name
-> Const (First (TextZipper Text)) (Editor Text Name)
forall t1 n t2 (f :: * -> *).
Functor f =>
(TextZipper t1 -> f (TextZipper t2))
-> Editor t1 n -> f (Editor t2 n)
editContentsL)
Maybe (Maybe TeamId)
mmTid <- Getting (First (Maybe TeamId)) ChatState (Maybe TeamId)
-> MH (Maybe (Maybe TeamId))
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name -> Const (First (Maybe TeamId)) (EditState Name))
-> ChatState -> Const (First (Maybe TeamId)) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name -> Const (First (Maybe TeamId)) (EditState Name))
-> ChatState -> Const (First (Maybe TeamId)) ChatState)
-> ((Maybe TeamId -> Const (First (Maybe TeamId)) (Maybe TeamId))
-> EditState Name -> Const (First (Maybe TeamId)) (EditState Name))
-> Getting (First (Maybe TeamId)) ChatState (Maybe TeamId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe TeamId -> Const (First (Maybe TeamId)) (Maybe TeamId))
-> EditState Name -> Const (First (Maybe TeamId)) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe TeamId -> f (Maybe TeamId))
-> EditState n -> f (EditState n)
esTeamId)
TeamId
tId <- do
case Maybe (Maybe TeamId)
mmTid of
Just (Just TeamId
i) -> TeamId -> MH TeamId
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return TeamId
i
Maybe (Maybe TeamId)
_ -> Maybe TeamId -> TeamId
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe TeamId -> TeamId) -> MH (Maybe TeamId) -> MH TeamId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting (Maybe TeamId) ChatState (Maybe TeamId)
-> MH (Maybe TeamId)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting (Maybe TeamId) ChatState (Maybe TeamId)
SimpleGetter ChatState (Maybe TeamId)
csCurrentTeamId
case Maybe (TextZipper Text)
maybeZipper of
Just TextZipper Text
z -> do
let col :: Int
col = (Int, Int) -> Int
forall a b. (a, b) -> b
snd ((Int, Int) -> Int) -> (Int, Int) -> Int
forall a b. (a -> b) -> a -> b
$ TextZipper Text -> (Int, Int)
forall a. TextZipper a -> (Int, Int)
Z.cursorPosition TextZipper Text
z
curLine :: Text
curLine = TextZipper Text -> Text
forall a. Monoid a => TextZipper a -> a
Z.currentLine TextZipper Text
z
Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> MH
(Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text))
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> MH
(Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)))
-> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> MH
(Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text))
forall a b. (a -> b) -> a -> b
$ case Int -> Text -> Maybe (Int, Text)
wordAtColumn Int
col Text
curLine of
Just (Int
startCol, Text
w)
| Text
userSigil Text -> Text -> Bool
`T.isPrefixOf` Text
w ->
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. a -> Maybe a
Just (AutocompletionType
ACUsers, Traversal' ChatState (EditState Name)
-> TeamId
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doUserAutoCompletion (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which TeamId
tId, HasCallStack => Text -> Text
Text -> Text
T.tail Text
w)
| Text
normalChannelSigil Text -> Text -> Bool
`T.isPrefixOf` Text
w ->
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. a -> Maybe a
Just (AutocompletionType
ACChannels, TeamId
-> Traversal' ChatState (EditState Name)
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doChannelAutoCompletion TeamId
tId (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which, HasCallStack => Text -> Text
Text -> Text
T.tail Text
w)
| Text
":" Text -> Text -> Bool
`T.isPrefixOf` Text
w Bool -> Bool -> Bool
&& AutocompleteContext -> Bool
autocompleteManual AutocompleteContext
ctx ->
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. a -> Maybe a
Just (AutocompletionType
ACEmoji, Traversal' ChatState (EditState Name)
-> AutocompletionType -> AutocompleteContext -> Text -> MH ()
doEmojiAutoCompletion (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which, HasCallStack => Text -> Text
Text -> Text
T.tail Text
w)
| Text
"```" Text -> Text -> Bool
`T.isPrefixOf` Text
w ->
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. a -> Maybe a
Just (AutocompletionType
ACCodeBlockLanguage, Traversal' ChatState (EditState Name)
-> AutocompletionType -> AutocompleteContext -> Text -> MH ()
doSyntaxAutoCompletion (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which, Int -> Text -> Text
T.drop Int
3 Text
w)
| Text
"/" Text -> Text -> Bool
`T.isPrefixOf` Text
w Bool -> Bool -> Bool
&& Int
startCol Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 ->
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. a -> Maybe a
Just (AutocompletionType
ACCommands, Traversal' ChatState (EditState Name)
-> TeamId
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doCommandAutoCompletion (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which TeamId
tId, HasCallStack => Text -> Text
Text -> Text
T.tail Text
w)
Maybe (Int, Text)
_ -> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. Maybe a
Nothing
Maybe (TextZipper Text)
_ -> Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
-> MH
(Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text))
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe
(AutocompletionType,
AutocompletionType -> AutocompleteContext -> Text -> MH (), Text)
forall a. Maybe a
Nothing
doEmojiAutoCompletion :: Traversal' ChatState (EditState Name)
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doEmojiAutoCompletion :: Traversal' ChatState (EditState Name)
-> AutocompletionType -> AutocompleteContext -> Text -> MH ()
doEmojiAutoCompletion Traversal' ChatState (EditState Name)
which AutocompletionType
ty AutocompleteContext
ctx Text
searchString = do
Session
session <- MH Session
getSession
EmojiCollection
em <- Getting EmojiCollection ChatState EmojiCollection
-> MH EmojiCollection
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ChatResources -> Const EmojiCollection ChatResources)
-> ChatState -> Const EmojiCollection ChatState
Lens' ChatState ChatResources
csResources((ChatResources -> Const EmojiCollection ChatResources)
-> ChatState -> Const EmojiCollection ChatState)
-> ((EmojiCollection -> Const EmojiCollection EmojiCollection)
-> ChatResources -> Const EmojiCollection ChatResources)
-> Getting EmojiCollection ChatState EmojiCollection
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(EmojiCollection -> Const EmojiCollection EmojiCollection)
-> ChatResources -> Const EmojiCollection ChatResources
Lens' ChatResources EmojiCollection
crEmoji)
Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> AutocompletionType
-> Text
-> MH ()
-> MH ()
withCachedAutocompleteResults (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx AutocompletionType
ty Text
searchString (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$
AsyncPriority -> IO (Maybe (MH ())) -> MH ()
doAsyncWith AsyncPriority
Preempt (IO (Maybe (MH ())) -> MH ()) -> IO (Maybe (MH ())) -> MH ()
forall a b. (a -> b) -> a -> b
$ do
[Text]
results <- Session -> EmojiCollection -> Text -> IO [Text]
getMatchingEmoji Session
session EmojiCollection
em Text
searchString
let alts :: [AutocompleteAlternative]
alts = Text -> AutocompleteAlternative
EmojiCompletion (Text -> AutocompleteAlternative)
-> [Text] -> [AutocompleteAlternative]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
results
Maybe (MH ()) -> IO (Maybe (MH ()))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MH ()) -> IO (Maybe (MH ())))
-> Maybe (MH ()) -> IO (Maybe (MH ()))
forall a b. (a -> b) -> a -> b
$ MH () -> Maybe (MH ())
forall a. a -> Maybe a
Just (MH () -> Maybe (MH ())) -> MH () -> Maybe (MH ())
forall a b. (a -> b) -> a -> b
$ Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
alts AutocompletionType
ty
doSyntaxAutoCompletion :: Traversal' ChatState (EditState Name)
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doSyntaxAutoCompletion :: Traversal' ChatState (EditState Name)
-> AutocompletionType -> AutocompleteContext -> Text -> MH ()
doSyntaxAutoCompletion Traversal' ChatState (EditState Name)
which AutocompletionType
ty AutocompleteContext
ctx Text
searchString = do
SyntaxMap
mapping <- Getting SyntaxMap ChatState SyntaxMap -> MH SyntaxMap
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ChatResources -> Const SyntaxMap ChatResources)
-> ChatState -> Const SyntaxMap ChatState
Lens' ChatState ChatResources
csResources((ChatResources -> Const SyntaxMap ChatResources)
-> ChatState -> Const SyntaxMap ChatState)
-> ((SyntaxMap -> Const SyntaxMap SyntaxMap)
-> ChatResources -> Const SyntaxMap ChatResources)
-> Getting SyntaxMap ChatState SyntaxMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(SyntaxMap -> Const SyntaxMap SyntaxMap)
-> ChatResources -> Const SyntaxMap ChatResources
Lens' ChatResources SyntaxMap
crSyntaxMap)
let allNames :: [Text]
allNames = Syntax -> Text
Sky.sShortname (Syntax -> Text) -> [Syntax] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SyntaxMap -> [Syntax]
forall k a. Map k a -> [a]
M.elems SyntaxMap
mapping
([Text]
prefixed, [Text]
notPrefixed) = (Text -> Bool) -> [Text] -> ([Text], [Text])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition Text -> Bool
isPrefixed ([Text] -> ([Text], [Text])) -> [Text] -> ([Text], [Text])
forall a b. (a -> b) -> a -> b
$ (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter Text -> Bool
match [Text]
allNames
match :: Text -> Bool
match = (((Text -> Text
T.toLower Text
searchString) Text -> Text -> Bool
`T.isInfixOf`) (Text -> Bool) -> (Text -> Text) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toLower)
isPrefixed :: Text -> Bool
isPrefixed = (((Text -> Text
T.toLower Text
searchString) Text -> Text -> Bool
`T.isPrefixOf`) (Text -> Bool) -> (Text -> Text) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toLower)
alts :: [AutocompleteAlternative]
alts = Text -> AutocompleteAlternative
SyntaxCompletion (Text -> AutocompleteAlternative)
-> [Text] -> [AutocompleteAlternative]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([Text] -> [Text]
forall a. Ord a => [a] -> [a]
sort [Text]
prefixed [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [Text] -> [Text]
forall a. Ord a => [a] -> [a]
sort [Text]
notPrefixed)
Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
alts AutocompletionType
ty
hiddenServerCommands :: [Text]
hiddenServerCommands :: [Text]
hiddenServerCommands =
[ Text
"settings"
, Text
"help"
, Text
"collapse"
, Text
"expand"
, Text
"logout"
, Text
"remove"
, Text
"msg"
, Text
"leave"
, Text
"join"
, Text
"search"
, Text
"shortcuts"
, Text
"open"
]
hiddenCommand :: Command -> Bool
hiddenCommand :: Command -> Bool
hiddenCommand Command
c = (Text -> Text
T.toLower (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Command -> Text
commandTrigger Command
c) Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
hiddenServerCommands
isDeletedCommand :: Command -> Bool
isDeletedCommand :: Command -> Bool
isDeletedCommand Command
cmd = Command -> ServerTime
commandDeleteAt Command
cmd ServerTime -> ServerTime -> Bool
forall a. Ord a => a -> a -> Bool
> Command -> ServerTime
commandCreateAt Command
cmd
doCommandAutoCompletion :: Traversal' ChatState (EditState Name)
-> TeamId
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doCommandAutoCompletion :: Traversal' ChatState (EditState Name)
-> TeamId
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doCommandAutoCompletion Traversal' ChatState (EditState Name)
which TeamId
tId AutocompletionType
ty AutocompleteContext
ctx Text
searchString = do
Session
session <- MH Session
getSession
Maybe (HashMap Text [AutocompleteAlternative])
mCache <- Getting
(First (HashMap Text [AutocompleteAlternative]))
ChatState
(HashMap Text [AutocompleteAlternative])
-> MH (Maybe (HashMap Text [AutocompleteAlternative]))
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> ChatState
-> Const (First (HashMap Text [AutocompleteAlternative])) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> ChatState
-> Const
(First (HashMap Text [AutocompleteAlternative])) ChatState)
-> ((HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> Getting
(First (HashMap Text [AutocompleteAlternative]))
ChatState
(HashMap Text [AutocompleteAlternative])
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe (AutocompleteState n) -> f (Maybe (AutocompleteState n)))
-> EditState n -> f (EditState n)
esAutocomplete((Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> ((HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> (HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name))
forall a a' (f :: * -> *).
Applicative f =>
(a -> f a') -> Maybe a -> f (Maybe a')
_Just((AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> ((HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name))
-> (HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name)
forall n (f :: * -> *).
Functor f =>
(HashMap Text [AutocompleteAlternative]
-> f (HashMap Text [AutocompleteAlternative]))
-> AutocompleteState n -> f (AutocompleteState n)
acCachedResponses)
Maybe AutocompletionType
mActiveTy <- Getting (First AutocompletionType) ChatState AutocompletionType
-> MH (Maybe AutocompletionType)
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> ChatState -> Const (First AutocompletionType) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> ChatState -> Const (First AutocompletionType) ChatState)
-> ((AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> Getting (First AutocompletionType) ChatState AutocompletionType
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> EditState Name
-> Const (First AutocompletionType) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe (AutocompleteState n) -> f (Maybe (AutocompleteState n)))
-> EditState n -> f (EditState n)
esAutocomplete((Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> ((AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> (AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> EditState Name
-> Const (First AutocompletionType) (EditState Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name))
forall a a' (f :: * -> *).
Applicative f =>
(a -> f a') -> Maybe a -> f (Maybe a')
_Just((AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> ((AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name))
-> (AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name)
forall n (f :: * -> *).
Functor f =>
(AutocompletionType -> f AutocompletionType)
-> AutocompleteState n -> f (AutocompleteState n)
acType)
let entry :: Maybe [AutocompleteAlternative]
entry = Text
-> HashMap Text [AutocompleteAlternative]
-> Maybe [AutocompleteAlternative]
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup Text
serverResponseKey (HashMap Text [AutocompleteAlternative]
-> Maybe [AutocompleteAlternative])
-> Maybe (HashMap Text [AutocompleteAlternative])
-> Maybe [AutocompleteAlternative]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe (HashMap Text [AutocompleteAlternative])
mCache
serverResponseKey :: Text
serverResponseKey = Text
""
lowerSearch :: Text
lowerSearch = Text -> Text
T.toLower Text
searchString
matches :: AutocompleteAlternative -> Bool
matches (CommandCompletion CompletionSource
_ Text
name Text
_ Text
desc) =
Text
lowerSearch Text -> Text -> Bool
`T.isInfixOf` (Text -> Text
T.toLower Text
name) Bool -> Bool -> Bool
||
Text
lowerSearch Text -> Text -> Bool
`T.isInfixOf` (Text -> Text
T.toLower Text
desc)
matches AutocompleteAlternative
_ = Bool
False
if (Maybe [AutocompleteAlternative] -> Bool
forall a. Maybe a -> Bool
isNothing Maybe [AutocompleteAlternative]
entry Bool -> Bool -> Bool
|| (Maybe AutocompletionType
mActiveTy Maybe AutocompletionType -> Maybe AutocompletionType -> Bool
forall a. Eq a => a -> a -> Bool
/= (AutocompletionType -> Maybe AutocompletionType
forall a. a -> Maybe a
Just AutocompletionType
ACCommands)))
then AsyncPriority -> IO (Maybe (MH ())) -> MH ()
doAsyncWith AsyncPriority
Preempt (IO (Maybe (MH ())) -> MH ()) -> IO (Maybe (MH ())) -> MH ()
forall a b. (a -> b) -> a -> b
$ do
let clientAlts :: [(CompletionSource, Text, Text, Text)]
clientAlts = Cmd -> (CompletionSource, Text, Text, Text)
mkAlt (Cmd -> (CompletionSource, Text, Text, Text))
-> [Cmd] -> [(CompletionSource, Text, Text, Text)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Cmd]
commandList
mkAlt :: Cmd -> (CompletionSource, Text, Text, Text)
mkAlt (Cmd Text
name Text
desc CmdArgs a
args CmdExec a
_) =
(CompletionSource
Client, Text
name, CmdArgs a -> Text
forall a. CmdArgs a -> Text
printArgSpec CmdArgs a
args, Text
desc)
Seq Command
serverCommands <- TeamId -> Bool -> Session -> IO (Seq Command)
MM.mmListCommandsForTeam TeamId
tId Bool
False Session
session
let filteredServerCommands :: [Command]
filteredServerCommands =
(Command -> Bool) -> [Command] -> [Command]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Command
c -> Bool -> Bool
not (Command -> Bool
hiddenCommand Command
c Bool -> Bool -> Bool
|| Command -> Bool
isDeletedCommand Command
c)) ([Command] -> [Command]) -> [Command] -> [Command]
forall a b. (a -> b) -> a -> b
$
Seq Command -> [Command]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList Seq Command
serverCommands
serverAlts :: [(CompletionSource, Text, Text, Text)]
serverAlts = Command -> (CompletionSource, Text, Text, Text)
mkTuple (Command -> (CompletionSource, Text, Text, Text))
-> [Command] -> [(CompletionSource, Text, Text, Text)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Command]
filteredServerCommands
mkTuple :: Command -> (CompletionSource, Text, Text, Text)
mkTuple Command
cmd =
( CompletionSource
Server
, Command -> Text
commandTrigger Command
cmd
, Command -> Text
commandAutoCompleteHint Command
cmd
, Command -> Text
commandAutoCompleteDesc Command
cmd
)
mkCompletion :: (CompletionSource, Text, Text, Text) -> AutocompleteAlternative
mkCompletion (CompletionSource
src, Text
name, Text
args, Text
desc) =
CompletionSource -> Text -> Text -> Text -> AutocompleteAlternative
CommandCompletion CompletionSource
src Text
name Text
args Text
desc
alts :: [AutocompleteAlternative]
alts = ((CompletionSource, Text, Text, Text) -> AutocompleteAlternative)
-> [(CompletionSource, Text, Text, Text)]
-> [AutocompleteAlternative]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CompletionSource, Text, Text, Text) -> AutocompleteAlternative
mkCompletion ([(CompletionSource, Text, Text, Text)]
-> [AutocompleteAlternative])
-> [(CompletionSource, Text, Text, Text)]
-> [AutocompleteAlternative]
forall a b. (a -> b) -> a -> b
$
[(CompletionSource, Text, Text, Text)]
clientAlts [(CompletionSource, Text, Text, Text)]
-> [(CompletionSource, Text, Text, Text)]
-> [(CompletionSource, Text, Text, Text)]
forall a. Semigroup a => a -> a -> a
<> [(CompletionSource, Text, Text, Text)]
serverAlts
Maybe (MH ()) -> IO (Maybe (MH ()))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MH ()) -> IO (Maybe (MH ())))
-> Maybe (MH ()) -> IO (Maybe (MH ()))
forall a b. (a -> b) -> a -> b
$ MH () -> Maybe (MH ())
forall a. a -> Maybe a
Just (MH () -> Maybe (MH ())) -> MH () -> Maybe (MH ())
forall a b. (a -> b) -> a -> b
$ do
Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
serverResponseKey [AutocompleteAlternative]
alts AutocompletionType
ty
let newAlts :: [AutocompleteAlternative]
newAlts = (AutocompleteAlternative -> AutocompleteAlternative -> Ordering)
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Text
-> AutocompleteAlternative -> AutocompleteAlternative -> Ordering
compareCommandAlts Text
searchString) ([AutocompleteAlternative] -> [AutocompleteAlternative])
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a b. (a -> b) -> a -> b
$
(AutocompleteAlternative -> Bool)
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a. (a -> Bool) -> [a] -> [a]
filter AutocompleteAlternative -> Bool
matches [AutocompleteAlternative]
alts
Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
newAlts AutocompletionType
ty
else case Maybe [AutocompleteAlternative]
entry of
Just [AutocompleteAlternative]
alts | Maybe AutocompletionType
mActiveTy Maybe AutocompletionType -> Maybe AutocompletionType -> Bool
forall a. Eq a => a -> a -> Bool
== AutocompletionType -> Maybe AutocompletionType
forall a. a -> Maybe a
Just AutocompletionType
ACCommands ->
let newAlts :: [AutocompleteAlternative]
newAlts = (AutocompleteAlternative -> AutocompleteAlternative -> Ordering)
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Text
-> AutocompleteAlternative -> AutocompleteAlternative -> Ordering
compareCommandAlts Text
searchString) ([AutocompleteAlternative] -> [AutocompleteAlternative])
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a b. (a -> b) -> a -> b
$
(AutocompleteAlternative -> Bool)
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a. (a -> Bool) -> [a] -> [a]
filter AutocompleteAlternative -> Bool
matches [AutocompleteAlternative]
alts
in Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
newAlts AutocompletionType
ty
Maybe [AutocompleteAlternative]
_ -> () -> MH ()
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
compareCommandAlts :: Text -> AutocompleteAlternative -> AutocompleteAlternative -> Ordering
compareCommandAlts :: Text
-> AutocompleteAlternative -> AutocompleteAlternative -> Ordering
compareCommandAlts Text
s (CommandCompletion CompletionSource
_ Text
nameA Text
_ Text
_)
(CommandCompletion CompletionSource
_ Text
nameB Text
_ Text
_) =
let isAPrefix :: Bool
isAPrefix = Text
s Text -> Text -> Bool
`T.isPrefixOf` Text
nameA
isBPrefix :: Bool
isBPrefix = Text
s Text -> Text -> Bool
`T.isPrefixOf` Text
nameB
in if Bool
isAPrefix Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
isBPrefix
then Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
nameA Text
nameB
else if Bool
isAPrefix
then Ordering
LT
else Ordering
GT
compareCommandAlts Text
_ AutocompleteAlternative
_ AutocompleteAlternative
_ = Ordering
LT
doUserAutoCompletion :: Traversal' ChatState (EditState Name)
-> TeamId
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doUserAutoCompletion :: Traversal' ChatState (EditState Name)
-> TeamId
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doUserAutoCompletion Traversal' ChatState (EditState Name)
which TeamId
tId AutocompletionType
ty AutocompleteContext
ctx Text
searchString = do
Session
session <- MH Session
getSession
UserId
myUid <- (ChatState -> UserId) -> MH UserId
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ChatState -> UserId
myUserId
ChannelId
cId <- Maybe ChannelId -> ChannelId
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ChannelId -> ChannelId)
-> MH (Maybe ChannelId) -> MH ChannelId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting (First ChannelId) ChatState ChannelId
-> MH (Maybe ChannelId)
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name -> Const (First ChannelId) (EditState Name))
-> ChatState -> Const (First ChannelId) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name -> Const (First ChannelId) (EditState Name))
-> ChatState -> Const (First ChannelId) ChatState)
-> ((ChannelId -> Const (First ChannelId) ChannelId)
-> EditState Name -> Const (First ChannelId) (EditState Name))
-> Getting (First ChannelId) ChatState ChannelId
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ChannelId -> Const (First ChannelId) ChannelId)
-> EditState Name -> Const (First ChannelId) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(ChannelId -> f ChannelId) -> EditState n -> f (EditState n)
esChannelId)
Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> AutocompletionType
-> Text
-> MH ()
-> MH ()
withCachedAutocompleteResults (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx AutocompletionType
ty Text
searchString (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$
AsyncPriority -> IO (Maybe (MH ())) -> MH ()
doAsyncWith AsyncPriority
Preempt (IO (Maybe (MH ())) -> MH ()) -> IO (Maybe (MH ())) -> MH ()
forall a b. (a -> b) -> a -> b
$ do
UserAutocomplete
ac <- Maybe TeamId
-> Maybe ChannelId -> Text -> Session -> IO UserAutocomplete
MM.mmAutocompleteUsers (TeamId -> Maybe TeamId
forall a. a -> Maybe a
Just TeamId
tId) (ChannelId -> Maybe ChannelId
forall a. a -> Maybe a
Just ChannelId
cId) Text
searchString Session
session
let active :: Seq User -> Seq User
active = (User -> Bool) -> Seq User -> Seq User
forall a. (a -> Bool) -> Seq a -> Seq a
Seq.filter (\User
u -> User -> UserId
userId User
u UserId -> UserId -> Bool
forall a. Eq a => a -> a -> Bool
/= UserId
myUid Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ User -> Bool
userDeleted User
u))
alts :: [AutocompleteAlternative]
alts = Seq AutocompleteAlternative -> [AutocompleteAlternative]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (Seq AutocompleteAlternative -> [AutocompleteAlternative])
-> Seq AutocompleteAlternative -> [AutocompleteAlternative]
forall a b. (a -> b) -> a -> b
$
((\User
u -> User -> Bool -> AutocompleteAlternative
UserCompletion User
u Bool
True) (User -> AutocompleteAlternative)
-> Seq User -> Seq AutocompleteAlternative
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Seq User -> Seq User
active (Seq User -> Seq User) -> Seq User -> Seq User
forall a b. (a -> b) -> a -> b
$ UserAutocomplete -> Seq User
MM.userAutocompleteUsers UserAutocomplete
ac)) Seq AutocompleteAlternative
-> Seq AutocompleteAlternative -> Seq AutocompleteAlternative
forall a. Semigroup a => a -> a -> a
<>
(Seq AutocompleteAlternative
-> (Seq User -> Seq AutocompleteAlternative)
-> Maybe (Seq User)
-> Seq AutocompleteAlternative
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Seq AutocompleteAlternative
forall a. Monoid a => a
mempty ((User -> AutocompleteAlternative)
-> Seq User -> Seq AutocompleteAlternative
forall a b. (a -> b) -> Seq a -> Seq b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\User
u -> User -> Bool -> AutocompleteAlternative
UserCompletion User
u Bool
False) (Seq User -> Seq AutocompleteAlternative)
-> (Seq User -> Seq User)
-> Seq User
-> Seq AutocompleteAlternative
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq User -> Seq User
active) (Maybe (Seq User) -> Seq AutocompleteAlternative)
-> Maybe (Seq User) -> Seq AutocompleteAlternative
forall a b. (a -> b) -> a -> b
$
UserAutocomplete -> Maybe (Seq User)
MM.userAutocompleteOutOfChannel UserAutocomplete
ac)
specials :: [SpecialMention]
specials = [ SpecialMention
MentionAll
, SpecialMention
MentionChannel
]
extras :: [AutocompleteAlternative]
extras = [ SpecialMention -> AutocompleteAlternative
SpecialMention SpecialMention
m | SpecialMention
m <- [SpecialMention]
specials
, (Text -> Text
T.toLower Text
searchString) Text -> Text -> Bool
`T.isPrefixOf` SpecialMention -> Text
specialMentionName SpecialMention
m
]
Maybe (MH ()) -> IO (Maybe (MH ()))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MH ()) -> IO (Maybe (MH ())))
-> Maybe (MH ()) -> IO (Maybe (MH ()))
forall a b. (a -> b) -> a -> b
$ MH () -> Maybe (MH ())
forall a. a -> Maybe a
Just (MH () -> Maybe (MH ())) -> MH () -> Maybe (MH ())
forall a b. (a -> b) -> a -> b
$ Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString ([AutocompleteAlternative]
alts [AutocompleteAlternative]
-> [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a. Semigroup a => a -> a -> a
<> [AutocompleteAlternative]
extras) AutocompletionType
ty
doChannelAutoCompletion :: TeamId
-> Traversal' ChatState (EditState Name)
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doChannelAutoCompletion :: TeamId
-> Traversal' ChatState (EditState Name)
-> AutocompletionType
-> AutocompleteContext
-> Text
-> MH ()
doChannelAutoCompletion TeamId
tId Traversal' ChatState (EditState Name)
which AutocompletionType
ty AutocompleteContext
ctx Text
searchString = do
Session
session <- MH Session
getSession
ClientChannels
cs <- Getting ClientChannels ChatState ClientChannels
-> MH ClientChannels
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting ClientChannels ChatState ClientChannels
Lens' ChatState ClientChannels
csChannels
Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> AutocompletionType
-> Text
-> MH ()
-> MH ()
withCachedAutocompleteResults (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx AutocompletionType
ty Text
searchString (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$ do
AsyncPriority -> IO (Maybe (MH ())) -> MH ()
doAsyncWith AsyncPriority
Preempt (IO (Maybe (MH ())) -> MH ()) -> IO (Maybe (MH ())) -> MH ()
forall a b. (a -> b) -> a -> b
$ do
Seq Channel
results <- TeamId -> Text -> Session -> IO (Seq Channel)
MM.mmAutocompleteChannels TeamId
tId Text
searchString Session
session
let alts :: [AutocompleteAlternative]
alts = Seq AutocompleteAlternative -> [AutocompleteAlternative]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (Seq AutocompleteAlternative -> [AutocompleteAlternative])
-> Seq AutocompleteAlternative -> [AutocompleteAlternative]
forall a b. (a -> b) -> a -> b
$ (Bool -> Channel -> AutocompleteAlternative
ChannelCompletion Bool
True (Channel -> AutocompleteAlternative)
-> Seq Channel -> Seq AutocompleteAlternative
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Seq Channel
inChannels) Seq AutocompleteAlternative
-> Seq AutocompleteAlternative -> Seq AutocompleteAlternative
forall a. Semigroup a => a -> a -> a
<>
(Bool -> Channel -> AutocompleteAlternative
ChannelCompletion Bool
False (Channel -> AutocompleteAlternative)
-> Seq Channel -> Seq AutocompleteAlternative
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Seq Channel
notInChannels)
(Seq Channel
inChannels, Seq Channel
notInChannels) = (Channel -> Bool) -> Seq Channel -> (Seq Channel, Seq Channel)
forall a. (a -> Bool) -> Seq a -> (Seq a, Seq a)
Seq.partition Channel -> Bool
isMember Seq Channel
results
isMember :: Channel -> Bool
isMember Channel
c = Maybe ClientChannel -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ClientChannel -> Bool) -> Maybe ClientChannel -> Bool
forall a b. (a -> b) -> a -> b
$ ChannelId -> ClientChannels -> Maybe ClientChannel
findChannelById (Channel -> ChannelId
channelId Channel
c) ClientChannels
cs
Maybe (MH ()) -> IO (Maybe (MH ()))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MH ()) -> IO (Maybe (MH ())))
-> Maybe (MH ()) -> IO (Maybe (MH ()))
forall a b. (a -> b) -> a -> b
$ MH () -> Maybe (MH ())
forall a. a -> Maybe a
Just (MH () -> Maybe (MH ())) -> MH () -> Maybe (MH ())
forall a b. (a -> b) -> a -> b
$ Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
alts AutocompletionType
ty
withCachedAutocompleteResults :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> AutocompletionType
-> Text
-> MH ()
-> MH ()
withCachedAutocompleteResults :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> AutocompletionType
-> Text
-> MH ()
-> MH ()
withCachedAutocompleteResults Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx AutocompletionType
ty Text
searchString MH ()
act = do
Maybe (HashMap Text [AutocompleteAlternative])
mCache <- Getting
(First (HashMap Text [AutocompleteAlternative]))
ChatState
(HashMap Text [AutocompleteAlternative])
-> MH (Maybe (HashMap Text [AutocompleteAlternative]))
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> ChatState
-> Const (First (HashMap Text [AutocompleteAlternative])) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> ChatState
-> Const
(First (HashMap Text [AutocompleteAlternative])) ChatState)
-> ((HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> Getting
(First (HashMap Text [AutocompleteAlternative]))
ChatState
(HashMap Text [AutocompleteAlternative])
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe (AutocompleteState n) -> f (Maybe (AutocompleteState n)))
-> EditState n -> f (EditState n)
esAutocomplete((Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name))
-> ((HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> (HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> EditState Name
-> Const
(First (HashMap Text [AutocompleteAlternative])) (EditState Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name))
forall a a' (f :: * -> *).
Applicative f =>
(a -> f a') -> Maybe a -> f (Maybe a')
_Just((AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name)))
-> ((HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name))
-> (HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> Maybe (AutocompleteState Name)
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(Maybe (AutocompleteState Name))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(HashMap Text [AutocompleteAlternative]
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(HashMap Text [AutocompleteAlternative]))
-> AutocompleteState Name
-> Const
(First (HashMap Text [AutocompleteAlternative]))
(AutocompleteState Name)
forall n (f :: * -> *).
Functor f =>
(HashMap Text [AutocompleteAlternative]
-> f (HashMap Text [AutocompleteAlternative]))
-> AutocompleteState n -> f (AutocompleteState n)
acCachedResponses)
Maybe AutocompletionType
mActiveTy <- Getting (First AutocompletionType) ChatState AutocompletionType
-> MH (Maybe AutocompletionType)
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> ChatState -> Const (First AutocompletionType) ChatState
Traversal' ChatState (EditState Name)
which((EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> ChatState -> Const (First AutocompletionType) ChatState)
-> ((AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> Getting (First AutocompletionType) ChatState AutocompletionType
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> EditState Name
-> Const (First AutocompletionType) (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe (AutocompleteState n) -> f (Maybe (AutocompleteState n)))
-> EditState n -> f (EditState n)
esAutocomplete((Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> EditState Name
-> Const (First AutocompletionType) (EditState Name))
-> ((AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> (AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> EditState Name
-> Const (First AutocompletionType) (EditState Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name))
forall a a' (f :: * -> *).
Applicative f =>
(a -> f a') -> Maybe a -> f (Maybe a')
_Just((AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name))
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name)))
-> ((AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name))
-> (AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> Maybe (AutocompleteState Name)
-> Const
(First AutocompletionType) (Maybe (AutocompleteState Name))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(AutocompletionType
-> Const (First AutocompletionType) AutocompletionType)
-> AutocompleteState Name
-> Const (First AutocompletionType) (AutocompleteState Name)
forall n (f :: * -> *).
Functor f =>
(AutocompletionType -> f AutocompletionType)
-> AutocompleteState n -> f (AutocompleteState n)
acType)
case AutocompletionType -> Maybe AutocompletionType
forall a. a -> Maybe a
Just AutocompletionType
ty Maybe AutocompletionType -> Maybe AutocompletionType -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe AutocompletionType
mActiveTy of
Bool
True ->
case Text
-> HashMap Text [AutocompleteAlternative]
-> Maybe [AutocompleteAlternative]
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup Text
searchString (HashMap Text [AutocompleteAlternative]
-> Maybe [AutocompleteAlternative])
-> Maybe (HashMap Text [AutocompleteAlternative])
-> Maybe [AutocompleteAlternative]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe (HashMap Text [AutocompleteAlternative])
mCache of
Just [AutocompleteAlternative]
alts -> Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
alts AutocompletionType
ty
Maybe [AutocompleteAlternative]
Nothing -> MH ()
act
Bool
False -> MH ()
act
setCompletionAlternatives :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives :: Traversal' ChatState (EditState Name)
-> AutocompleteContext
-> Text
-> [AutocompleteAlternative]
-> AutocompletionType
-> MH ()
setCompletionAlternatives Traversal' ChatState (EditState Name)
which AutocompleteContext
ctx Text
searchString [AutocompleteAlternative]
alts AutocompletionType
ty = do
Maybe (EditState Name)
mVal <- Getting (First (EditState Name)) ChatState (EditState Name)
-> MH (Maybe (EditState Name))
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse Getting (First (EditState Name)) ChatState (EditState Name)
Traversal' ChatState (EditState Name)
which
case Maybe (EditState Name)
mVal of
Maybe (EditState Name)
Nothing -> () -> MH ()
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just EditState Name
esVal -> do
let list :: GenericList Name Vector AutocompleteAlternative
list = Name
-> Vector AutocompleteAlternative
-> Int
-> GenericList Name Vector AutocompleteAlternative
forall (t :: * -> *) n e.
Foldable t =>
n -> t e -> Int -> GenericList n t e
L.list (Name -> Name
CompletionList (Name -> Name) -> Name -> Name
forall a b. (a -> b) -> a -> b
$ Editor Text Name -> Name
forall a n. Named a n => a -> n
getName (Editor Text Name -> Name) -> Editor Text Name -> Name
forall a b. (a -> b) -> a -> b
$ EditState Name
esValEditState Name
-> Getting (Editor Text Name) (EditState Name) (Editor Text Name)
-> Editor Text Name
forall s a. s -> Getting a s a -> a
^.Getting (Editor Text Name) (EditState Name) (Editor Text Name)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> EditState n -> f (EditState n)
esEditor) ([AutocompleteAlternative] -> Vector AutocompleteAlternative
forall a. [a] -> Vector a
V.fromList ([AutocompleteAlternative] -> Vector AutocompleteAlternative)
-> [AutocompleteAlternative] -> Vector AutocompleteAlternative
forall a b. (a -> b) -> a -> b
$ [AutocompleteAlternative] -> [AutocompleteAlternative]
forall a. [a] -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList [AutocompleteAlternative]
alts) Int
1
pending :: Maybe Text
pending = EditState Name
esValEditState Name
-> Getting (Maybe Text) (EditState Name) (Maybe Text) -> Maybe Text
forall s a. s -> Getting a s a -> a
^.Getting (Maybe Text) (EditState Name) (Maybe Text)
forall n (f :: * -> *).
Functor f =>
(Maybe Text -> f (Maybe Text)) -> EditState n -> f (EditState n)
esAutocompletePending
state :: AutocompleteState Name
state = AutocompleteState { _acPreviousSearchString :: Text
_acPreviousSearchString = Text
searchString
, _acCompletionList :: GenericList Name Vector AutocompleteAlternative
_acCompletionList =
GenericList Name Vector AutocompleteAlternative
list GenericList Name Vector AutocompleteAlternative
-> (GenericList Name Vector AutocompleteAlternative
-> GenericList Name Vector AutocompleteAlternative)
-> GenericList Name Vector AutocompleteAlternative
forall a b. a -> (a -> b) -> b
& (Maybe Int -> Identity (Maybe Int))
-> GenericList Name Vector AutocompleteAlternative
-> Identity (GenericList Name Vector AutocompleteAlternative)
forall n (t :: * -> *) e (f :: * -> *).
Functor f =>
(Maybe Int -> f (Maybe Int))
-> GenericList n t e -> f (GenericList n t e)
L.listSelectedL ((Maybe Int -> Identity (Maybe Int))
-> GenericList Name Vector AutocompleteAlternative
-> Identity (GenericList Name Vector AutocompleteAlternative))
-> Maybe Int
-> GenericList Name Vector AutocompleteAlternative
-> GenericList Name Vector AutocompleteAlternative
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe Int
forall a. Maybe a
Nothing
, _acCachedResponses :: HashMap Text [AutocompleteAlternative]
_acCachedResponses = [(Text, [AutocompleteAlternative])]
-> HashMap Text [AutocompleteAlternative]
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList [(Text
searchString, [AutocompleteAlternative]
alts)]
, _acType :: AutocompletionType
_acType = AutocompletionType
ty
}
case Maybe Text
pending of
Just Text
val | Text
val Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
searchString -> do
(EditState Name -> Identity (EditState Name))
-> ChatState -> Identity ChatState
Traversal' ChatState (EditState Name)
which((EditState Name -> Identity (EditState Name))
-> ChatState -> Identity ChatState)
-> ((Maybe (AutocompleteState Name)
-> Identity (Maybe (AutocompleteState Name)))
-> EditState Name -> Identity (EditState Name))
-> (Maybe (AutocompleteState Name)
-> Identity (Maybe (AutocompleteState Name)))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (AutocompleteState Name)
-> Identity (Maybe (AutocompleteState Name)))
-> EditState Name -> Identity (EditState Name)
forall n (f :: * -> *).
Functor f =>
(Maybe (AutocompleteState n) -> f (Maybe (AutocompleteState n)))
-> EditState n -> f (EditState n)
esAutocomplete ((Maybe (AutocompleteState Name)
-> Identity (Maybe (AutocompleteState Name)))
-> ChatState -> Identity ChatState)
-> (Maybe (AutocompleteState Name)
-> Maybe (AutocompleteState Name))
-> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= \Maybe (AutocompleteState Name)
prev ->
let newState :: AutocompleteState Name
newState = case Maybe (AutocompleteState Name)
prev of
Maybe (AutocompleteState Name)
Nothing ->
AutocompleteState Name
state
Just AutocompleteState Name
oldState ->
AutocompleteState Name
state AutocompleteState Name
-> (AutocompleteState Name -> AutocompleteState Name)
-> AutocompleteState Name
forall a b. a -> (a -> b) -> b
& (HashMap Text [AutocompleteAlternative]
-> Identity (HashMap Text [AutocompleteAlternative]))
-> AutocompleteState Name -> Identity (AutocompleteState Name)
forall n (f :: * -> *).
Functor f =>
(HashMap Text [AutocompleteAlternative]
-> f (HashMap Text [AutocompleteAlternative]))
-> AutocompleteState n -> f (AutocompleteState n)
acCachedResponses ((HashMap Text [AutocompleteAlternative]
-> Identity (HashMap Text [AutocompleteAlternative]))
-> AutocompleteState Name -> Identity (AutocompleteState Name))
-> HashMap Text [AutocompleteAlternative]
-> AutocompleteState Name
-> AutocompleteState Name
forall s t a b. ASetter s t a b -> b -> s -> t
.~
Text
-> [AutocompleteAlternative]
-> HashMap Text [AutocompleteAlternative]
-> HashMap Text [AutocompleteAlternative]
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert Text
searchString [AutocompleteAlternative]
alts (AutocompleteState Name
oldStateAutocompleteState Name
-> Getting
(HashMap Text [AutocompleteAlternative])
(AutocompleteState Name)
(HashMap Text [AutocompleteAlternative])
-> HashMap Text [AutocompleteAlternative]
forall s a. s -> Getting a s a -> a
^.Getting
(HashMap Text [AutocompleteAlternative])
(AutocompleteState Name)
(HashMap Text [AutocompleteAlternative])
forall n (f :: * -> *).
Functor f =>
(HashMap Text [AutocompleteAlternative]
-> f (HashMap Text [AutocompleteAlternative]))
-> AutocompleteState n -> f (AutocompleteState n)
acCachedResponses)
in AutocompleteState Name -> Maybe (AutocompleteState Name)
forall a. a -> Maybe a
Just AutocompleteState Name
newState
EventM Name ChatState () -> MH ()
forall a. EventM Name ChatState a -> MH a
mh (EventM Name ChatState () -> MH ())
-> EventM Name ChatState () -> MH ()
forall a b. (a -> b) -> a -> b
$ ViewportScroll Name -> forall s. EventM Name s ()
forall n. ViewportScroll n -> forall s. EventM n s ()
vScrollToBeginning (ViewportScroll Name -> forall s. EventM Name s ())
-> ViewportScroll Name -> forall s. EventM Name s ()
forall a b. (a -> b) -> a -> b
$ Name -> ViewportScroll Name
forall n. n -> ViewportScroll n
viewportScroll (Name -> ViewportScroll Name) -> Name -> ViewportScroll Name
forall a b. (a -> b) -> a -> b
$ Name -> Name
CompletionList (Name -> Name) -> Name -> Name
forall a b. (a -> b) -> a -> b
$ Editor Text Name -> Name
forall a n. Named a n => a -> n
getName (Editor Text Name -> Name) -> Editor Text Name -> Name
forall a b. (a -> b) -> a -> b
$ EditState Name
esValEditState Name
-> Getting (Editor Text Name) (EditState Name) (Editor Text Name)
-> Editor Text Name
forall s a. s -> Getting a s a -> a
^.Getting (Editor Text Name) (EditState Name) (Editor Text Name)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> EditState n -> f (EditState n)
esEditor
Bool -> MH () -> MH ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (AutocompleteContext -> Bool
autocompleteFirstMatch AutocompleteContext
ctx) (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$
Traversal' ChatState (EditState Name) -> Direction -> MH ()
tabComplete (EditState Name -> f (EditState Name)) -> ChatState -> f ChatState
Traversal' ChatState (EditState Name)
which Direction
Forwards
Maybe Text
_ ->
() -> MH ()
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
wordAtColumn :: Int -> Text -> Maybe (Int, Text)
wordAtColumn :: Int -> Text -> Maybe (Int, Text)
wordAtColumn Int
i Text
t =
let tokens :: [Text]
tokens = (Char -> Char -> Bool) -> Text -> [Text]
T.groupBy (\Char
a Char
b -> Char -> Bool
isSpace Char
a Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Bool
isSpace Char
b) Text
t
go :: Int -> Int -> [Text] -> Maybe (Int, Text)
go Int
_ Int
j [Text]
_ | Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Maybe (Int, Text)
forall a. Maybe a
Nothing
go Int
col Int
j [Text]
ts = case [Text]
ts of
[] -> Maybe (Int, Text)
forall a. Maybe a
Nothing
(Text
w:[Text]
rest) | Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Text -> Int
T.length Text
w Bool -> Bool -> Bool
&& Bool -> Bool
not (Char -> Bool
isSpace (Char -> Bool) -> Char -> Bool
forall a b. (a -> b) -> a -> b
$ HasCallStack => Text -> Char
Text -> Char
T.head Text
w) -> (Int, Text) -> Maybe (Int, Text)
forall a. a -> Maybe a
Just (Int
col, Text
w)
| Bool
otherwise -> Int -> Int -> [Text] -> Maybe (Int, Text)
go (Int
col Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Text -> Int
T.length Text
w) (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
w) [Text]
rest
in Int -> Int -> [Text] -> Maybe (Int, Text)
go Int
0 Int
i [Text]
tokens