diff --git a/source/src/command.cpp b/source/src/command.cpp index d1ba629c..7df6f66e 100644 --- a/source/src/command.cpp +++ b/source/src/command.cpp @@ -866,9 +866,36 @@ void commandcomplete(char *s) concatstring(s, t); } if(!s[1]) return; - char *cp = s; + + int o = 0; //offset + + while(*s) {s++; o++;} //seek to end + s--; //last character + + for (int i = o; i > 1; i--) //seek backwards + { + s--; + o--; + if (*s == ';') //until ';' is found + { + s++; break; //string after ';' + } + } + + char *openblock = strrchr(s+1, '('); //find last open parenthesis + char *closeblock = strrchr(s+1, ')'); //find last closed parenthesis + + if (openblock) + { + if (!closeblock || closeblock < openblock) //open block + s = openblock; + } + + char *cp = s; //part to complete + for(int i = (int)strlen(s) - 1; i > 0; i--) - if(s[i] == ';' || s[i] == ' ') { cp = s + i; break; } + if(s[i] == ' ') { cp = s + i; break; } //testing for command/argument needs completion + bool init = false; if(completesize < 0) { @@ -878,8 +905,10 @@ void commandcomplete(char *s) } completeval *cdata = NULL; - char *end = strchr(s, ' '); - if(end && end <= cp) + + char *end = strchr(s+1, ' '); //find end of command name + + if(end && end <= cp) //full command is present { string command; copystring(command, s+1, min(size_t(end-s), sizeof(command))); @@ -892,18 +921,19 @@ void commandcomplete(char *s) loopv(cdata->dirlist) listfiles(cdata->dirlist[i], cdata->ext, cdata->list); } - if(*cp == '/' || *cp == ';') + if(*cp == '/' || *cp == ';' + || cp == s && (*cp == ' ' || *cp == '(')) { // commandname completion int idx = 0; enumerate(*idents, ident, id, if(!strncasecmp(id.name, cp+1, completesize) && idx++==completeidx) { cp[1] = '\0'; - concatstring(s, id.name); + strcpy(s+1, id.name); //concatstring/copystring will crash because of overflow } ); completeidx++; - if(completeidx>=idx) completeidx = 0; + if(completeidx>=idx) completeidx = 1; } else if(!cdata) return; else if(cdata->type==COMPLETE_NICK) nickcomplete(s); @@ -915,13 +945,13 @@ void commandcomplete(char *s) if(!strncasecmp(cdata->list[j], cp + 1, completesize)) { cp[1] = '\0'; - concatstring(s, cdata->list[j]); + strcpy(cp+1, cdata->list[j]); //concatstring/copystring will crash because of overflow completeidx = j; break; } } completeidx++; - if(completeidx >= cdata->list.length()) completeidx = 0; + if(completeidx >= cdata->list.length()) completeidx = 1; } } diff --git a/source/src/docs.cpp b/source/src/docs.cpp index abbfd748..7ca10925 100644 --- a/source/src/docs.cpp +++ b/source/src/docs.cpp @@ -390,6 +390,7 @@ int numargs(char *args) switch(*argstart) { case '[': if(*(t-1) != ']') continue; break; + case '(': if(*(t-1) != ')') continue; break; case '"': if(*(t-1) != '"') continue; break; default: break; } @@ -404,18 +405,73 @@ void renderdoc(int x, int y, int doch) if(!docvisible) return; char *exp = getcurcommand(); - if(!exp || *exp != '/' || strlen(exp) < 2) return; - char *c = exp+1; + int o = 0; //offset + int f = 0; //last found + + while (*exp) + {exp++; o++; if (*exp == ';' || (*exp == ' ' && f == o-1)) f = o;} exp--; + + if (f > 0) + { + for (int i = o - f - 1; i > 0; i--) exp--; + if (o > f + 1) exp++; + } + + else {for (int i = o; i > 1; i--) exp--;} + + char *openblock = strrchr(exp+1, '('); //find last open parenthesis + char *closeblock = strrchr(exp+1, ')'); //find last closed parenthesis + char *temp = NULL; + + if (openblock) + { + if (!closeblock || closeblock < openblock) //open block + temp = openblock + 1; + } + + if(!exp || (*exp != '/' && f == 0) || strlen(exp) < 2) return; + + char *c = exp+1; if (f > 0) c = exp; + char *d = NULL; if (temp) d = temp; + size_t clen = strlen(c); + size_t dlen = 0; if (d) dlen = strlen(d); + + bool nc = false; //tests if text after open parenthesis is not a command + + docident *ident = NULL; + for(size_t i = 0; i < clen; i++) // search first matching cmd doc by stripping arguments of exp from right to left { char *end = c+clen-i; if(!*end || *end == ' ') { string cmd; + string dmd; + copystring(cmd, c, clen-i+1); - docident *ident = docidents.access(cmd); + + if (d && !nc && dlen > 1) + { + for(size_t j = 0; j < dlen; j++) //test text after parenthesis + { + char *dnd = d+dlen-j; + if(!*dnd || *dnd == ' ') + { + copystring(dmd, d, dlen-j+1); + ident = docidents.access(dmd); + } + if (j == dlen-1 && !ident) + nc = true; + } + } + else + { + nc = true; + ident = docidents.access(cmd); + } + if(ident) { vector doclines; @@ -436,7 +492,10 @@ void renderdoc(int x, int y, int doch) if(ident->arguments.length() > 0) // args { extern textinputbuffer cmdline; + + if (d && dlen > 1) c = d; char *args = strchr(c, ' '); + int arg = -1; if(args) @@ -457,6 +516,7 @@ void renderdoc(int x, int y, int doch) if(arg >= 0) // multipart idents need a fixed argument offset { char *c = cmd; + if (!nc) c = dmd; while((c = strchr(c, ' ')) && c++) arg--; }