summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib.c5
-rw-r--r--lib.h1
-rw-r--r--parser.c27
-rw-r--r--struct.c38
-rw-r--r--struct.h1
-rw-r--r--txr.114
6 files changed, 74 insertions, 12 deletions
diff --git a/lib.c b/lib.c
index 5d2724fe..e578b308 100644
--- a/lib.c
+++ b/lib.c
@@ -5053,7 +5053,10 @@ val unuse_package(val unuse_list, val package_in)
return unuse_package_list;
}
-static val symbol_visible(val package, val sym)
+/* symbol_visible assumes the perspective that package
+ * is the current package!
+ */
+val symbol_visible(val package, val sym)
{
val name = symbol_name(sym);
type_check (package, PKG);
diff --git a/lib.h b/lib.h
index 87b23465..4d359f60 100644
--- a/lib.h
+++ b/lib.h
@@ -800,6 +800,7 @@ val use_sym(val use_list, val package);
val unuse_sym(val symbol, val package);
val use_package(val use_list, val package);
val unuse_package(val unuse_list, val package);
+val symbol_visible(val package, val sym);
val find_symbol(val str, val package);
val intern(val str, val package);
val unintern(val sym, val package);
diff --git a/parser.c b/parser.c
index 11249945..20e5a094 100644
--- a/parser.c
+++ b/parser.c
@@ -686,18 +686,20 @@ static val get_visible_syms(val package, int is_cur)
static void find_matching_syms(lino_completions_t *cpl,
val package, val prefix,
- val line_prefix, char par,
+ val line_prefix, char kind,
val force_qualify)
{
- int is_cur = package == cur_package;
+ val is_cur = tnil(package == cur_package);
val qualify = tnil(force_qualify || !is_cur);
val pkg_name = if2(qualify,
if3(package == keyword_package && !force_qualify,
lit(""),
package_name(package)));
- val syms;
+ val syms = ((kind == 'S' || kind == 'M')
+ ? hash_keys((get_slot_syms(package, is_cur, tnil(kind == 'M'))))
+ : get_visible_syms(package, is_cur != nil));
- for (syms = get_visible_syms(package, is_cur); syms; syms = cdr(syms)) {
+ for ( ; syms; syms = cdr(syms)) {
val sym = car(syms);
val name = symbol_name(sym);
val found = if3(cpl->substring,
@@ -707,7 +709,7 @@ static void find_matching_syms(lino_completions_t *cpl,
if (found) {
val comple;
- switch (par) {
+ switch (kind) {
case '(':
if (!fboundp(sym) && !mboundp(sym) && !special_operator_p(sym))
continue;
@@ -716,6 +718,9 @@ static void find_matching_syms(lino_completions_t *cpl,
if (!boundp(sym) && !lookup_fun(nil, sym))
continue;
break;
+ case 'M':
+ case 'S':
+ break;
default:
break;
}
@@ -812,13 +817,19 @@ static void provide_completions(const char *data,
char prev = (end > data) ? end[-1] : 0;
char pprev = (end > data + 1) ? end[-2] : 0;
int quote = (pprev == '^' || pprev == '\'' || pprev == '#');
- int meth = (pprev == '.');
int ppar = (pprev == '(');
int dwim = (prev == '[');
- char par = (!pprev || (!quote && !meth && !ppar) || dwim) ? prev : 0;
+ int par = (prev == '(');
+ int slot = (prev == '.');
+ int meth = (pprev == '.') && (dwim || par);
+ char kind = (slot
+ ? 'S'
+ : (meth
+ ? 'M'
+ : (!pprev || (!quote && !ppar) || dwim) ? prev : 0));
find_matching_syms(cpl, or2(package, cur_package),
- sym_pfx, line_pfx, par, if2(package, null(keyword)));
+ sym_pfx, line_pfx, kind, if2(package, null(keyword)));
}
}
}
diff --git a/struct.c b/struct.c
index 84977da6..57870980 100644
--- a/struct.c
+++ b/struct.c
@@ -1507,6 +1507,44 @@ val method_name(val fun)
return nil;
}
+val get_slot_syms(val package, val is_current, val method_only)
+{
+ val result_hash = make_hash(nil, nil, nil);
+ val sth_iter = hash_begin(struct_type_hash);
+ val sth_cell;
+
+ while ((sth_cell = hash_next(sth_iter))) {
+ val stype = cdr(sth_cell);
+ val sl_iter;
+ struct struct_type *st = coerce(struct struct_type *, stype->co.handle);
+
+ for (sl_iter = st->slots; sl_iter; sl_iter = cdr(sl_iter)) {
+ val slot = car(sl_iter);
+
+ if (gethash(result_hash, slot))
+ continue;
+
+ if (!is_current && symbol_package(slot) != package)
+ continue;
+
+ if (!symbol_visible(package, slot))
+ continue;
+
+ if (method_only) {
+ loc ptr = lookup_static_slot(st, slot);
+ if (nullocp(ptr))
+ continue;
+ if (!functionp(deref(ptr)))
+ continue;
+ }
+
+ sethash(result_hash, slot, t);
+ }
+ }
+
+ return result_hash;
+}
+
static_def(struct cobj_ops struct_type_ops =
cobj_ops_init(eq, struct_type_print, struct_type_destroy,
struct_type_mark, cobj_hash_op))
diff --git a/struct.h b/struct.h
index d7f30f0d..10f87f72 100644
--- a/struct.h
+++ b/struct.h
@@ -63,4 +63,5 @@ val super_method(val strct, val slotsym);
val uslot(val slot);
val umethod(val slot, struct args *);
val method_name(val fun);
+val get_slot_syms(val package, val is_current, val method_only);
void struct_init(void);
diff --git a/txr.1 b/txr.1
index 22ced1b2..9c7cdf34 100644
--- a/txr.1
+++ b/txr.1
@@ -52097,11 +52097,19 @@ sequence Ctrl-X Tab.
When completion is invoked with Tab or Ctrl-X Tab, the listener looks at a few
of the trailing characters to the left of the cursor position to determine the
applicable list of completions. Completions are determined from among the \*(TL symbols which have
-global variable, function, macro and symbolic macro bindings. Symbols which
-have operator binding are also taken into consideration. If a
+global variable, function, macro and symbolic macro bindings, as well
+as the static and instance slots of structures. Symbols which
+have operator bindings are also taken into consideration. If a
package-qualified symbol is completed, then completion is restricted to that
package. Keyword symbol completion is restricted to the contents of the keyword
-package.
+package. The namespaces which are searched for symbols are restricted according
+to preceding character syntax. For instance if the characters
+.code ".("
+or
+.code ".["
+immediately precede the prefix, then only those symbols are considered
+which are methods: that is, each is the static slot of at least one structure,
+in which that static slots holds a function.
The difference between Tab and Ctrl-X Tab is that Tab completion looks only for
prefix matches among the eligible identifiers. Thus it is a pure completion in