diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-03-21 06:22:42 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-03-21 06:22:42 -0700 |
commit | 7e2f1500f34098be4a0cc0b2130cffb3a729793b (patch) | |
tree | 18e9a0b5e4136d8379f583fdd2069748f6648ac8 | |
parent | c2dec325d87de8be8917e7b52f118f4664a9e13a (diff) | |
download | txr-7e2f1500f34098be4a0cc0b2130cffb3a729793b.tar.gz txr-7e2f1500f34098be4a0cc0b2130cffb3a729793b.tar.bz2 txr-7e2f1500f34098be4a0cc0b2130cffb3a729793b.zip |
listener: completion sensitive for slots and methods.
When completing .prefix[TAB], .(prefix[TAB] or .[prefix[TAB],
restrict identifiers to the appropriate namespace. The former
will report only symbols from the relevant package which are
struct slots; the latter further restricts it to those which
are static slots defined as functions.
* lib.c (symbol_visible): Static function becomes extern.
* lib.h (symbol_visible): Declared.
* parser.c (find_matching_syms): par parameter is renamed
kind and can hold additional values 'S' (slots) and 'M'
(methods). New get_slot_syms function is used to fetch the
slots, as necessary, instead of the visible syms, if the
kind is 'S' or 'M'. The same loop as before (with the minor
change of recognizing 'S' and 'M' also) performs the prefix
matching.
(provide_completions): Recognize . .( and .[ prefix,
calculating the kind argument of find_matching_syms in
a new way.
* struct.c (get_slot_syms): New function.
* struct.h (get_slot_syms): Declared.
* txr.1: Add some notes about this under the description of
completion. The full rules are not given though; let the
user discover.
-rw-r--r-- | lib.c | 5 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | parser.c | 27 | ||||
-rw-r--r-- | struct.c | 38 | ||||
-rw-r--r-- | struct.h | 1 | ||||
-rw-r--r-- | txr.1 | 14 |
6 files changed, 74 insertions, 12 deletions
@@ -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); @@ -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); @@ -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))); } } } @@ -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)) @@ -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); @@ -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 |