1 inherit Tools.Hilfe.Evaluator;
4 mapping myvars = ([ ]);
7 Stdio.Readline readln = Stdio.Readline(Stdio.stdin);
8 mapping(string:mixed) constants = constants; //fetching Evaluator constants
10 mapping base_objects(Evaluator e)
12 return all_constants() + e->constants + e->variables + myvars;
15 void set_server_filepath(object o)
20 array(object|array(string)) resolv(Evaluator e, array completable,
21 void|object base, void|string type)
23 if (e->variables->DEBUG_COMPLETIONS)
24 e->safe_write("resolv(%O, %O, %O)\n", completable, base, type);
25 if (!sizeof(completable))
26 return ({ base, completable, type });
27 if (stringp(completable[0]) &&
28 completable[0] == array_sscanf(completable[0], "%[ \t\r\n]")[0])
29 return ({ base, completable[1..], type });
30 if (typeof_token(completable[0]) == "argumentgroup" && type != "autodoc")
31 return resolv(e, completable, master()->show_doc(base), "autodoc");
33 if(!base && completable[0]==".")
35 if (sizeof(completable) == 1)
36 return ({ 0, completable, "module" });
41 // quick and dirty attempt to load a local module
42 base=compile_string(sprintf("object o=.%s;", completable[1]), 0)()->o;
45 return ({ 0, completable, type });
47 return resolv(e, completable[2..], base, "module");
48 return resolv(e, completable[2..], base);
51 if (!base && sizeof(completable) > 1)
53 if (completable[0] == "master" && sizeof(completable) >=2
54 && typeof_token(completable[1]) == "argumentgroup")
56 return resolv(e, completable[2..], master(), "object");
58 if (base=base_objects(e)[completable[0]])
60 return resolv(e, completable[1..], base, "object");
62 if ((sizeof(completable) > 1)
63 && (base=master()->root_module[completable[0]]))
64 return resolv(e, completable[1..], base, "module");
65 return ({ 0, completable, type });
68 if (sizeof(completable) > 1)
71 if (reference[completable[0]] && sizeof(completable) > 1)
72 return resolv(e, completable[1..], base);
73 if (type == "autodoc")
75 if (typeof_token(completable[0]) == "symbol"
76 && (newbase = base->findObject(completable[0])))
77 return resolv(e, completable[1..], newbase, type);
78 else if (sizeof(completable) > 2
79 && typeof_token(completable[0]) == "argumentgroup"
80 && typeof_token(completable[1]) == "reference")
81 return resolv(e, completable[2..], base, type);
83 return ({ base, completable, type });
85 if (!functionp(base) && (newbase=base[completable[0]]) )
86 return resolv(e, completable[1..], newbase, type);
88 return ({ base, completable, type });
92 array get_resolvable(array tokens, void|int debug)
95 array completable = ({});
98 foreach(reverse(tokens);; string token)
100 string _tokentype = typeof_token(token);
103 write(sprintf("%O = %s\n", token, _tokentype));
105 if ( ( _tokentype == "reference" &&
106 (!tokentype || tokentype == "symbol"))
107 || (_tokentype == "symbol" && (!tokentype
108 || (< "reference", "referencegroup",
109 "argumentgroup" >)[tokentype]))
110 || ( (<"argumentgroup", "referencegroup" >)[_tokentype]
111 && (!tokentype || tokentype == "reference"))
114 completable += ({ token });
115 tokentype = _tokentype;
117 else if (_tokentype == "whitespace")
123 // keep the last whitespace
124 if (arrayp(tokens) && sizeof(tokens) &&
125 typeof_token(tokens[-1]) == "whitespace")
126 completable = ({ " " }) + completable;
127 return reverse(completable);
131 void set(mapping vars)
136 void load_hilferc() {
137 if(string home=getenv("HOME")||getenv("USERPROFILE"))
138 if(string s=Stdio.read_file(home+"/.hilferc"))
139 map(s/"\n", add_buffer);
143 array tokenize(string input)
145 array tokens = Parser.Pike.split(input);
146 if (variables->DEBUG_COMPLETIONS)
147 readln->message(sprintf("\n\ntokenize(%O): %O\n\n", input, tokens));
148 // drop the linebreak that split appends
149 if (tokens[-1] == "\n")
150 tokens = tokens[..<1];
151 else if (tokens[-1][-1] == '\n')
152 tokens[-1] = tokens[-1][..<1];
154 tokens = Parser.Pike.group(tokens);
160 void handle_completions(string key)
162 // write("KEY IS : "+key);
163 mixed old_handler = master()->get_inhibit_compile_errors();
164 HilfeCompileHandler handler = HilfeCompileHandler(sizeof(backtrace()));
165 master()->set_inhibit_compile_errors(handler);
168 input = readln->gettext()[..readln->getcursorpos()-1];
169 // write("INPUT IS "+input);
170 array|string completions;
174 tokens = tokenize(input);
176 // write("Tokens are : %O",tokens);
181 if (objectp(error) && error->is_unterminated_string_error)
183 // THE set_attribute and get_attribute tab completion is here
188 mixed error5 = catch{
189 toks = tokenize(input+"\")");
194 b=search(toks,"set_attribute");
195 if(b!=(sizeof(toks)-2)) //second last token is set_attribute, last token is the string inside with double quotes.
196 b=search(toks,"query_attribute");
197 if(b==(sizeof(toks)-2)) //because if set/query_attribute is at the end it will be second last token, which is -2
199 if(b!=-1) //not needed
201 if((myvars[toks[b-2]])) //usually it is like x->y->z->set_attribute(""), so z will be our const/var which is -2 from loc.
203 completions = indices(base_objects(this)[toks[b-2]]->get_attributes());
204 string rest = toks[b+1][1]-"\"";
207 array(string) temp = ({ });
209 int l = sizeof(rest);
210 foreach(completions, string str)
212 if(str[0 .. (l-1)]==rest)
214 temp = temp + ({str});
219 completions = (string)(temp[0]-rest);
230 mixed outer_error = catch{
231 array tokens3 = ({ });
233 tokens3 = tokenize(input+"\")");
238 if((a=search(tokens3,"OBJ"))!=-1)
241 if(arrayp(tokens3[b]))
243 completions = show_path_completions(tokens3[a+1][1]);
246 throw("no toks[a+1]\n");
251 completions = get_file_completions((input/"\"")[-1]);
259 error = Error.mkerror(error);
260 readln->message(sprintf("%s\nAn error occurred, attempting to complete your input!\nPlease include the backtrace above and the line below in your report:\ninput: %s\n", error->describe(), input));
264 if (tokens && !completions)
266 array completable = get_resolvable(tokens, variables->DEBUG_COMPLETIONS);
268 if (completable && sizeof(completable))
272 completions = get_module_completions(completable);
274 error = Error.mkerror(error);
276 else if (!tokens || !sizeof(tokens))
277 completions = sort(indices(master()->root_module)) +
278 sort(indices(base_objects(this)));
279 // FIXME: base_objects should not be sorted like this
281 if (!completions || !sizeof(completions))
283 string token = tokens[-1];
284 if( sizeof(tokens) >= 2 && typeof_token(token) == "whitespace" )
287 if (variables->DEBUG_COMPLETIONS)
288 readln->message(sprintf("type: %s\n", typeof_token(token)));
290 completions = sort(indices(master()->root_module)) +
291 sort(indices(base_objects(this)));
294 switch(typeof_token(token))
299 completions = (array)(infix+seperator);
305 completions += (array)prefix;
307 foreach(reverse(tokens);; string token)
311 completions += ({ group[token] }) ;
319 readln->message(sprintf("%s\nAn error occurred, attempting to complete your input!\nPlease include the backtrace above and the lines below in your report:\ninput: %s\ntokens: %O\ncompletable: %O\n", error->describe(), input, tokens, completable, ));
321 else if (variables->DEBUG_COMPLETIONS)
322 readln->message(sprintf("input: %s\ntokens: %O\ncompletable: %O\ncompletions: %O\n", input, tokens, completable, completions));
324 handler->show_errors();
325 handler->show_warnings();
326 master()->set_inhibit_compile_errors(old_handler);
327 // write("Completions are %O",completions);
328 if(completions && sizeof(completions))
330 if(stringp(completions))
332 readln->insert(completions, readln->getcursorpos());
336 readln->list_completions(completions);
341 mixed show_path_completions(string cur_path)
343 cur_path = cur_path - "\""; //trimming "s in suppose "/"-> /
353 parts = cur_path/"/";
356 cur_path = parts[0 .. sizeof(parts)-2]*"/";
365 mixed error2 = catch{
366 a = server_fp->path_to_object(cur_path);
371 objs=a->get_inventory();
372 foreach(objs, object x)
375 x_s = x->query_attribute("OBJ_PATH") - cur_path - "/";
377 x_s = x->query_attribute("OBJ_PATH") - "/";
378 mixed error3 = catch{
379 if(x_s[0 .. sizeof(rest)-1]==rest)
380 demo = demo + ({ x_s });
385 demo = demo[0]-(rest);
389 else if(sizeof(demo)!=0)
391 string common = String.common_prefix(demo);
392 if((common!="")&&((common-rest)!=""))
393 demo = common-(rest);
400 mapping reftypes = ([ "module":".",
409 array low_get_module_completions(array completable, object base, void|string type, void|int(0..1) space)
411 if (variables->DEBUG_COMPLETIONS)
412 safe_write(sprintf("low_get_module_completions(%O\n, %O, %O, %O)\n", completable, base, type, space));
417 mapping other = ([]);
418 array modules = ({});
421 if (base && !sizeof(completable))
425 if (type == "autodoc")
426 return ({ reftypes[base->objtype||base->objects[0]->objtype]||"" });
428 return ({ reftypes[type||"object"] });
430 return ({ reftypes->object });
431 else if(functionp(base))
432 return ({ reftypes->function });
433 else if (programp(base))
434 return ({ reftypes->program });
439 if (!base && sizeof(completable) && completable[0] == ".")
441 array modules = sort(get_dir("."));
442 if (sizeof(completable) > 1)
444 modules = Array.filter(modules, has_prefix, completable[1]);
445 if (sizeof(modules) == 1)
446 return ({ (modules[0]/".")[0][sizeof(completable[1])..] });
447 string prefix = String.common_prefix(modules)[sizeof(completable[1])..];
451 if (sizeof(completable) == 2)
461 if (type == "autodoc")
463 if (variables->DEBUG_COMPLETIONS)
464 safe_write("autodoc without base\n");
467 other = base_objects(this);
468 base = master()->root_module;
471 if (type == "autodoc")
474 modules = Array.uniq(Array.flatten(base->docGroups->objects->name));
482 modules = sort(indices(base));
484 error = Error.mkerror(error);
488 modules += indices(other);
490 if (sizeof(completable) == 1)
492 if (type == "autodoc"
493 && typeof_token(completable[0]) == "argumentgroup")
497 return ({ reftypes->object });
498 if (reference[completable[0]])
500 if (!stringp(completable[0]))
504 modules = sort((array(string))modules);
505 modules = Array.filter(modules, has_prefix, completable[0]);
506 string prefix = String.common_prefix(modules);
509 if (prefix == completable[0] && sizeof(modules)>1 && (base[prefix]||other[prefix]))
510 return modules + low_get_module_completions(({}), base[prefix]||other[prefix], type, space);
512 prefix = prefix[sizeof(completable[0])..];
516 if (sizeof(modules)>1)
518 else if (!sizeof(modules))
526 if(other && other[module])
528 thismodule = other[module];
531 else if (intp(base[module]) || floatp(base[module]) || stringp(base[module]) )
535 thismodule = base[module];
540 return low_get_module_completions(({}), thismodule, type, space);
544 if (completable && sizeof(completable))
546 if ( (< "reference", "argumentgroup" >)[typeof_token(completable[0])])
547 return low_get_module_completions(completable[1..], base, type||reference[completable[0]], space);
549 safe_write(sprintf("UNHANDLED CASE: completable: %O\nbase: %O\n", completable, base));
555 array|string get_module_completions(array completable)
557 array rest = completable;
565 if (completable[-1]==' ')
568 completable = completable[..<1];
571 if (sizeof(completable) > 1)
572 [base, rest, type] = resolv(this, completable);
574 if (variables->DEBUG_COMPLETIONS)
575 safe_write(sprintf("get_module_completions(%O): %O, %O, %O\n", completable, base, rest, type));
576 array completions = low_get_module_completions(rest, base, type, space);
577 if (sizeof(completions) == 1)
578 return completions[0];
582 array|string get_file_completions(string path)
585 if ( (< "", ".", ".." >)[path-"../"] )
588 if (!sizeof(path) || path[0] != '/')
591 string dir = dirname(path);
592 string file = basename(path);
595 files += get_dir(dir);
601 array completions = Array.filter(files, has_prefix, file);
602 string prefix = String.common_prefix(completions)[sizeof(file)..];
609 mapping filetypes = ([ "dir":"/", "lnk":"@", "reg":"" ]);
611 if (sizeof(completions) == 1 && file_stat(dir+"/"+completions[0])->isdir )
617 foreach(completions; int count; string item)
619 Stdio.Stat stat = file_stat(dir+"/"+item);
621 completions[count] += filetypes[stat->type]||"";
623 stat = file_stat(dir+"/"+item, 1);
624 if (stat->type == "lnk")
625 completions[count] += filetypes["lnk"];