mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-09 04:59:31 -06:00
fast word completion for functions names in the shell
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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])
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user