/* Aplwc - A Programming Language With Constraints * * Copyright (C) 2026 Peter Mikkelsen * * This file is part of aplwc. * * Aplwc 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. * * Aplwc 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 aplwc. If not, see . */ #include #include #include #include #include "aplwc_internal.h" struct completion_state { const struct aplwc *aplwc; int num; const char *word; const int wordlen; }; static char **generate(struct aplwc *, const char *, char *(*)(struct completion_state *)); static char *completions_syscmd(struct completion_state *); char ** aplwc_autocomplete(struct aplwc *aplwc, const char *line, int start, int end) { int len = end-start; char *word = malloc(sizeof(char) * len+1); char **completions = NULL; memcpy(word, line+start, len); word[len] = 0; struct aplwc_eval_context *context = aplwc_new_eval_context(aplwc); aplwc_scan_line(context, line); struct aplwc_token *tok = NULL; for(size_t i = 0; (i < context->n_tokens) && (tok == NULL); i++) if(((size_t)start >= context->tokens[i]->offset_start) && ((size_t)end <= context->tokens[i]->offset_end + 1)) tok = context->tokens[i]; if(tok) switch(tok->tag) { case APLWC_TOKEN_SYSCMD: completions = generate(aplwc, word, completions_syscmd); break; default: break; } free(word); aplwc_free_eval_context(context); return completions; } static char ** generate(struct aplwc *aplwc, const char *word, char *(*fn)(struct completion_state *)) { char **completions = NULL; struct completion_state state = { .aplwc = aplwc, .num = 0, .word = word, .wordlen = strlen(word), }; char *c; int index = 0; while((c = fn(&state))){ index++; completions = realloc(completions, sizeof(*completions) * (index + 1)); completions[index-1] = c; completions[index] = NULL; } return completions; } static char * completions_syscmd(struct completion_state *state) { struct aplwc_syscmd *syscmd; while((syscmd = state->aplwc->syscmds[state->num++])){ const char *name = syscmd->name; if(strncmp(name, state->word+1, state->wordlen-1) == 0){ int len = strlen(name); char *result = malloc(sizeof(char) * (len + 2)); result[0] = ')'; memcpy(result+1, name, sizeof(char) * (len+1)); return result; } } return NULL; }