This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */

staticvoidcomplete_function(EditLine*el){//Add left parenthesis to function name. el_insertstr(el,"(");}staticvoidcomplete_members(EditLine*el,constchar*str,constchar*str_type,intstr_len,char*dot){char*table=strdup(str);if(!table){perror("While tab-completing");return;}//Get only the table name (without partial member name).if(dot){*(table+(dot-str))='\0';}//Insert a dot after the table name.if(!strncmp(str_type,"table",5)){el_insertstr(el,".");str_len++;}//Check if the substring before dot is a valid table name.constchar*t_type=get_type_name(table);if(t_type&&!strncmp("table",t_type,5)){//Get string of members of the table.char*cmd=afmt("do local s=\"\"; for i in pairs(%s) do s=s..i..\"\\n\" end return(s) end",table);if(!cmd){perror("While tab-completing.");gotocomplete_members_exit;}size_tmembers_len;char*members=run_cmd(cmd,&members_len);free(cmd);if(!members){perror("While communication with daemon");gotocomplete_members_exit;}//Split members by newline.char*members_tok=strdup(members);free(members);if(!members_tok){gotocomplete_members_exit;}char*token=strtok(members_tok,"\n");intmatches=0;char*lastmatch=NULL;if(!dot||dot-str+1==strlen(str)){//Prints all members.while(token){char*member=afmt("%s.%s",table,token);

token=strtok(NULL,"\n");matches++;}}else{//Print members matching the current line.while(token){if(str&&starts_with(token,dot+1)){constchar*member_type=get_type_name(afmt("%s.%s",table,token));if(member_type){printf("\n%s.%s (%s)",table,token,member_type);

char*hist_file=NULL;char*data_home=getenv("XDG_DATA_HOME");//Check whether $XDG_DATA_HOME is set.if(!data_home||*data_home=='\0'){constchar*home=getenv("HOME");//This should be set on any POSIX compliant OS, even for nobody//Create necessary folders.char*dirs[3]={afmt("%s/.local",home),afmt("%s/.local/share",home),afmt("%s/.local/share/kresd/",home)};boolok=true;for(inti=0;i<3;i++){if(mkdir(dirs[i],0755)&&errno!=EEXIST){ok=false;break;}}if(ok){hist_file=afmt("%s/.local/share/kresd/"HISTORY_FILE,home);}}else{if(!mkdir(afmt("%s/kresd/",data_home),0755)||errno==EEXIST){hist_file=afmt("%s/kresd/"HISTORY_FILE,data_home);}}//Load history fileif(hist_file){history(hist,&ev,H_LOAD,hist_file);}else{perror("While opening history file");}