<commit_before>module Idris.Apropos where

import Idris.AbsSyntax
import Idris.Core.Evaluate (ctxtAlist, Def(..))
import Idris.Core.TT (Name(..), Type, TT(..), NameType(..), Binder(..), Const(..),
                      lookupCtxtExact, toAlist)
import Idris.Docstrings (Docstring, containsText)

import Data.List (nub)
import qualified Data.Text as T

-- | Find definitions that are relevant to some string. Relevance is one or
-- more of the following:
--
-- * the string is a substring of the name
--
-- * the string occurs in the documentation string
--
-- * the type of the definition is apropos
apropos :: IState -> T.Text -> [Name]
apropos ist what = let defs = ctxtAlist (tt_ctxt ist)
                       docs = toAlist (idris_docstrings ist)
                   in nub (map fst (filter (isApropos what) defs) ++
                           map fst (filter (isApropos what) docs))

textIn :: T.Text -> T.Text -> Bool
textIn a b = T.isInfixOf (T.toLower a) (T.toLower b)

class Apropos a where
  isApropos :: T.Text -> a -> Bool

instance Apropos Name where
  isApropos str (UN n)     = textIn str n
  isApropos str (NS n' ns) = isApropos str n' || any (textIn str) ns
  -- Handle special names from stdlib
  isApropos str n | (n == unitTy || n == unitCon) && str == T.pack "()" = True
                  | n == falseTy && str == T.pack "_|_" = True
                  | (n == pairTy || n == pairCon) && str == T.pack "," = True
                  | n == eqTy && str == T.pack "=" = True
                  | n == eqCon && (T.toLower str) == T.pack "refl" = True
                  | (n == sigmaTy || n == existsCon) && str == T.pack "**" = True
  isApropos _   _          = False -- we don't care about case blocks, MNs, etc

instance Apropos Def where
  isApropos str (Function ty tm) = isApropos str ty
  isApropos str (TyDecl _ ty) = isApropos str ty
  isApropos str (Operator ty _ _) = isApropos str ty<commit_msg>Split :apropos queries at spaces, treat as conjunction<commit_after>module Idris.Apropos where

import Idris.AbsSyntax
import Idris.Core.Evaluate (ctxtAlist, Def(..))
import Idris.Core.TT (Name(..), Type, TT(..), NameType(..), Binder(..), Const(..),
                      lookupCtxtExact, toAlist)
import Idris.Docstrings (Docstring, containsText)

import Data.List (nub)
import qualified Data.Text as T

-- | Find definitions that are relevant to all space-delimited components of
-- some string. Relevance is one or more of the following:
--
-- * the string is a substring of the name
--
-- * the string occurs in the documentation string
--
-- * the type of the definition is apropos
apropos :: IState -> T.Text -> [Name]
apropos ist what = let defs = ctxtAlist (tt_ctxt ist)
                       docs = toAlist (idris_docstrings ist)
                   in nub (map fst (isAproposAll parts defs) ++
                           map fst (isAproposAll parts docs))
  where isAproposAll [] xs = xs
        isAproposAll (what:more) xs = filter (isApropos what)
                                             (isAproposAll more xs)
        parts = filter ((> 0) . T.length) . T.splitOn (T.pack " ") $ what

textIn :: T.Text -> T.Text -> Bool
textIn a b = T.isInfixOf (T.toLower a) (T.toLower b)

class Apropos a where
  isApropos :: T.Text -> a -> Bool

instance Apropos Name where
  isApropos str (UN n)     = textIn str n
  isApropos str (NS n' ns) = isApropos str n' || any (textIn str) ns
  -- Handle special names from stdlib
  isApropos str n | (n == unitTy || n == unitCon) && str == T.pack "()" = True
                  | n == falseTy && str == T.pack "_|_" = True
                  | (n == pairTy || n == pairCon) && str == T.pack "," = True
                  | n == eqTy && str == T.pack "=" = True
                  | n == eqCon && (T.toLower str) == T.pack "refl" = True
                  | (n == sigmaTy || n == existsCon) && str == T.pack "**" = True
  isApropos _   _          = False -- we don't care about case blocks, MNs, etc

instance Apropos Def where
  isApropos str (Function ty tm) = isApropos str ty
  isApropos str (TyDecl _ ty) = isApropos str ty
  isApropos str (Operator ty _ _) = isApropos str ty
{'fraction_non_alphanumeric': 0.12647839729664495, 'fraction_numerical': 0.0002413709872073377, 'mean_word_length': 2.2299298519095867, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1030520', 'n_tokens_mistral': 1395, 'n_tokens_neox': 1345, 'n_words': 476}