mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-23 19:42:50 -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)
|
-> Haskeline.completeFilename (left,right)
|
||||||
CmplIdent _ pref
|
CmplIdent _ pref
|
||||||
-> case pgfenv gfenv of
|
-> 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 (length pref) []
|
||||||
_ -> ret 0 []
|
_ -> ret 0 []
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -627,6 +627,32 @@ void namespace_iter(Namespace<V> map, PgfItor* itor, PgfExn *err)
|
|||||||
return;
|
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>
|
template <class V>
|
||||||
Namespace<V> namespace_map(Namespace<V> map, std::function<ref<V>(ref<V>)> f)
|
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_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
|
PGF_API
|
||||||
void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
|
void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
|
||||||
PgfText *cat, PgfItor *itor, PgfExn *err)
|
PgfText *cat, PgfItor *itor, PgfExn *err)
|
||||||
|
|||||||
@@ -336,6 +336,10 @@ PGF_API_DECL
|
|||||||
void pgf_iter_functions(PgfDB *db, PgfRevision revision,
|
void pgf_iter_functions(PgfDB *db, PgfRevision revision,
|
||||||
PgfItor *itor, PgfExn *err);
|
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
|
PGF_API_DECL
|
||||||
void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
|
void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
|
||||||
PgfText *cat, PgfItor *itor, PgfExn *err);
|
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
|
PGF_INTERNAL
|
||||||
void texticmp(PgfText *t1, PgfText *t2, int res[2])
|
void texticmp(PgfText *t1, PgfText *t2, int res[2])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
PGF_INTERNAL_DECL
|
PGF_INTERNAL_DECL
|
||||||
int textcmp(PgfText *t1, PgfText *t2);
|
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.
|
/* Performs both case-insensitive and case-sensitive comparison.
|
||||||
* The first element in res contains the result from
|
* The first element in res contains the result from
|
||||||
* the case-insensitive comparison. The second the result
|
* the case-insensitive comparison. The second the result
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ module PGF2 (-- * PGF
|
|||||||
Cat,categories,categoryContext,categoryProbability,
|
Cat,categories,categoryContext,categoryProbability,
|
||||||
|
|
||||||
-- ** Functions
|
-- ** Functions
|
||||||
Fun, functions, functionsByCat,
|
Fun, functions, functionsByPrefix, functionsByCat,
|
||||||
functionType, functionIsConstructor, functionProbability,
|
functionType, functionIsConstructor, functionProbability,
|
||||||
|
|
||||||
-- ** Expressions
|
-- ** Expressions
|
||||||
@@ -1094,6 +1094,26 @@ functions p =
|
|||||||
name <- peekText key
|
name <- peekText key
|
||||||
writeIORef ref $ (name : names)
|
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
|
-- | List of all functions defined in the abstract syntax
|
||||||
functionsByCat :: PGF -> Cat -> [Fun]
|
functionsByCat :: PGF -> Cat -> [Fun]
|
||||||
functionsByCat p cat =
|
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 :: 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_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)
|
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