fast word completion for functions names in the shell

This commit is contained in:
Krasimir Angelov
2023-03-02 10:28:00 +01:00
parent adc8a2fa29
commit f7ca8afa81
8 changed files with 87 additions and 2 deletions

View File

@@ -525,7 +525,7 @@ wordCompletion gfenv (left,right) = do
-> Haskeline.completeFilename (left,right)
CmplIdent _ pref
-> case pgfenv gfenv of
(_,Just pgf,_) -> ret (length pref) [Haskeline.simpleCompletion name | name <- functions pgf, isPrefixOf pref name]
(_,Just pgf,_) -> ret (length pref) [Haskeline.simpleCompletion name | name <- functionsByPrefix pgf pref]
_ -> ret (length pref) []
_ -> ret 0 []
where

View File

@@ -627,6 +627,32 @@ void namespace_iter(Namespace<V> map, PgfItor* itor, PgfExn *err)
return;
}
template <class V>
void namespace_iter_prefix(Namespace<V> map, PgfText *prefix, PgfItor* itor, PgfExn *err)
{
if (map == 0)
return;
int cmp = textcmp_prefix(prefix,&map->value->name);
if (cmp < 0)
namespace_iter_prefix(map->left, prefix, itor, err);
else if (cmp > 0)
namespace_iter_prefix(map->right, prefix, itor, err);
else {
namespace_iter_prefix(map->left, prefix, itor, err);
if (err->type != PGF_EXN_NONE)
return;
itor->fn(itor, &map->value->name, map->value.as_object(), err);
if (err->type != PGF_EXN_NONE)
return;
namespace_iter_prefix(map->right, prefix, itor, err);
if (err->type != PGF_EXN_NONE)
return;
}
}
template <class V>
Namespace<V> namespace_map(Namespace<V> map, std::function<ref<V>(ref<V>)> f)
{

View File

@@ -487,6 +487,19 @@ void pgf_iter_functions(PgfDB *db, PgfRevision revision,
} PGF_API_END
}
PGF_API
void pgf_iter_functions_by_prefix(PgfDB *db, PgfRevision revision,
PgfText *prefix, PgfItor *itor, PgfExn *err)
{
PGF_API_BEGIN {
DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = db->revision2pgf(revision);
pgf_exn_clear(err);
namespace_iter_prefix(pgf->abstract.funs, prefix, itor, err);
} PGF_API_END
}
PGF_API
void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
PgfText *cat, PgfItor *itor, PgfExn *err)

View File

@@ -336,6 +336,10 @@ PGF_API_DECL
void pgf_iter_functions(PgfDB *db, PgfRevision revision,
PgfItor *itor, PgfExn *err);
PGF_API_DECL
void pgf_iter_functions_by_prefix(PgfDB *db, PgfRevision revision,
PgfText *prefix, PgfItor *itor, PgfExn *err);
PGF_API_DECL
void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
PgfText *cat, PgfItor *itor, PgfExn *err);

View File

@@ -16,6 +16,22 @@ int textcmp(PgfText *t1, PgfText *t2)
}
}
PGF_INTERNAL
int textcmp_prefix(PgfText *t1, PgfText *t2)
{
for (size_t i = 0; ; i++) {
if (i >= t1->size)
return 0;
if (i >= t2->size)
return 1;
if (t1->text[i] > t2->text[i])
return 1;
else if (t1->text[i] < t2->text[i])
return -1;
}
}
PGF_INTERNAL
void texticmp(PgfText *t1, PgfText *t2, int res[2])
{

View File

@@ -5,6 +5,10 @@
PGF_INTERNAL_DECL
int textcmp(PgfText *t1, PgfText *t2);
/* The same as textcmp but returns 0 if t1 is a prefix of t2. */
PGF_INTERNAL_DECL
int textcmp_prefix(PgfText *t1, PgfText *t2);
/* Performs both case-insensitive and case-sensitive comparison.
* The first element in res contains the result from
* the case-insensitive comparison. The second the result

View File

@@ -24,7 +24,7 @@ module PGF2 (-- * PGF
Cat,categories,categoryContext,categoryProbability,
-- ** Functions
Fun, functions, functionsByCat,
Fun, functions, functionsByPrefix, functionsByCat,
functionType, functionIsConstructor, functionProbability,
-- ** Expressions
@@ -1094,6 +1094,26 @@ functions p =
name <- peekText key
writeIORef ref $ (name : names)
-- | List of all functions whose names start with a given prefix
functionsByPrefix :: PGF -> String -> [Fun]
functionsByPrefix p prefix =
unsafePerformIO $ do
ref <- newIORef []
(withText prefix $ \c_prefix ->
allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr
withPgfExn "functions" (pgf_iter_functions_by_prefix (a_db p) c_revision c_prefix itor)
fs <- readIORef ref
return (reverse fs))
where
getFunctions :: IORef [String] -> ItorCallback
getFunctions ref itor key _ exn = do
names <- readIORef ref
name <- peekText key
writeIORef ref $ (name : names)
-- | List of all functions defined in the abstract syntax
functionsByCat :: PGF -> Cat -> [Fun]
functionsByCat p cat =

View File

@@ -173,6 +173,8 @@ foreign import ccall pgf_category_prob :: Ptr PgfDB -> Ptr PGF -> Ptr PgfText ->
foreign import ccall pgf_iter_functions :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall pgf_iter_functions_by_prefix :: Ptr PgfDB -> Ptr PGF -> Ptr PgfText -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall pgf_iter_functions_by_cat :: Ptr PgfDB -> Ptr PGF -> Ptr PgfText -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall pgf_function_type :: Ptr PgfDB -> Ptr PGF -> Ptr PgfText -> Ptr PgfUnmarshaller -> Ptr PgfExn -> IO (StablePtr Type)