{-| Module : Client.Commands.TabCompletion Description : Common tab-completion logic Copyright : (c) Eric Mertens, 2016-2020 License : ISC Maintainer : emertens@gmail.com -} module Client.Commands.TabCompletion where import Client.Commands.Types import Client.Commands.WordCompletion import Client.Message import Client.State import Client.State.Focus import Client.State.Network import Client.State.Window import Client.State.Channel import Control.Lens import qualified Data.HashMap.Strict as HashMap import Irc.Identifier import Irc.UserInfo -- | Provides no tab completion for client commands noClientTab :: Bool -> ClientCommand String noClientTab _ st _ = commandFailure st -- | Provides no tab completion for network commands noNetworkTab :: Bool -> NetworkCommand String noNetworkTab _ _ st _ = commandFailure st -- | Provides no tab completion for channel commands noChannelTab :: Bool -> ChannelCommand String noChannelTab _ _ _ st _ = commandFailure st -- | Provides nickname based tab completion for client commands simpleClientTab :: Bool -> ClientCommand String simpleClientTab isReversed st _ = nickTabCompletion isReversed st -- | Provides nickname based tab completion for network commands simpleNetworkTab :: Bool -> NetworkCommand String simpleNetworkTab isReversed _ st _ = nickTabCompletion isReversed st -- | Provides nickname based tab completion for channel commands simpleChannelTab :: Bool -> ChannelCommand String simpleChannelTab isReversed _ _ st _ = nickTabCompletion isReversed st simpleTabCompletion :: Prefix a => WordCompletionMode {- ^ word completion mode -} -> [a] {- ^ hints -} -> [a] {- ^ all completions -} -> Bool {- ^ reversed order -} -> ClientState {- ^ client state -} -> IO CommandResult simpleTabCompletion = simpleTabCompletion' (' ' /=) simpleTabCompletion' :: Prefix a => (Char -> Bool) {- ^ valid characters -} -> WordCompletionMode {- ^ word completion mode -} -> [a] {- ^ hints -} -> [a] {- ^ all completions -} -> Bool {- ^ reversed order -} -> ClientState {- ^ client state -} -> IO CommandResult simpleTabCompletion' p mode hints completions isReversed st = case traverseOf clientTextBox tryCompletion st of Nothing -> commandFailure st Just st' -> commandSuccess st' where tryCompletion = wordComplete p mode isReversed hints completions -- | Complete the nickname at the current cursor position using the -- userlist for the currently focused channel (if any) nickTabCompletion :: Bool {- ^ reversed -} -> ClientState -> IO CommandResult nickTabCompletion isReversed st = simpleTabCompletion' isNickChar mode hint completions isReversed st where hint = activeNicks st completions = currentCompletionList st mode = currentNickCompletionMode st isNickChar :: Char -> Bool isNickChar x = inrange 'a' 'z' || inrange 'A' 'Z' || inrange '0' '9' || x `elem` "-[\\]^_`{}|#" where inrange lo hi = lo <= x && x <= hi activeNicks :: ClientState -> [Identifier] activeNicks st = case view clientFocus st of focus@(ChannelFocus network channel) -> toListOf ( clientWindows . ix focus . winMessages . each . wlSummary . folding chatActor . filtered isActive . filtered isNotSelf ) st where isActive n = HashMap.member n userMap self = preview ( clientConnection network . csNick ) st isNotSelf n = case self of Nothing -> True Just s -> n /= s userMap = view ( clientConnection network . csChannels . ix channel . chanUsers) st _ -> [] where -- Returns the 'Identifier' of the nickname responsible for -- the window line when that action was significant enough to -- be considered a hint for tab completion. chatActor :: IrcSummary -> Maybe Identifier chatActor (ChatSummary who) = Just $! userNick who chatActor _ = Nothing