aboutsummaryrefslogtreecommitdiffstats
path: root/bruiser/CompletionHints.c
diff options
context:
space:
mode:
Diffstat (limited to 'bruiser/CompletionHints.c')
-rw-r--r--bruiser/CompletionHints.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/bruiser/CompletionHints.c b/bruiser/CompletionHints.c
new file mode 100644
index 0000000..76d460d
--- /dev/null
+++ b/bruiser/CompletionHints.c
@@ -0,0 +1,274 @@
+
+/***************************************************Project Mutator****************************************************/
+//-*-c++-*-
+/*first line intentionally left blank.*/
+/*the source code for bruiser's auto-completion and suggestions.*/
+/*Copyright (C) 2017 Farzad Sadeghi
+
+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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/
+/**********************************************************************************************************************/
+/*included modules*/
+/*project headers*/
+#include "./lua-5.3.4/src/lua.h"
+#include "./lua-5.3.4/src/lauxlib.h"
+#include "./lua-5.3.4/src/lualib.h"
+/*standard headers*/
+#include "inttypes.h"
+#include "stdbool.h"
+#include "stddef.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+#include "unistd.h"
+/*other*/
+#include "CompletionHints.h"
+#include "completions.h"
+#include "linenoise/linenoise.h"
+/**********************************************************************************************************************/
+size_t get_str_len(const char* str) {
+ int size_counter = 0;
+ while (true) {
+ if (str[size_counter] != '\0') {
+ size_counter++;
+ } else {
+ return size_counter;
+ }
+ }
+}
+
+int devi_find_last_word(char const * const str, char* delimiters, int delimiter_size) {
+ size_t str_len = get_str_len(str);
+
+ for (int i = 0; i < delimiter_size; ++i) {
+ if (delimiters[i] == str[str_len-1]) return -1;
+ }
+
+ for (int i = str_len -1; i >=0; --i) {
+ for (int j = 0; j < delimiter_size;++j) {
+ if (delimiters[j] == str[i]) {
+ return i + 1;
+ } else {
+ /*intentionally left blank*/
+ }
+ }
+ }
+
+ return 0;
+}
+
+word_pos_t devi_find_middle_word(char const * const str, char* delimiters, int delimiter_size, size_t pos) {
+ size_t str_len = get_str_len(str);
+ word_pos_t result;
+ result.begin = -1;
+ result.end = -1;
+
+ if (NULL == str) return result;
+
+ bool begin_matched = false;
+ bool end_matched = false;
+
+ for (int i = 0; i < delimiter_size; ++i) {
+ if (str[pos] == delimiters[i]) {
+ return result;
+ }
+ }
+
+ for (int i = pos; i >=0; --i) {
+ for (int j = 0; j < delimiter_size;++j) {
+ if (delimiters[j] == str[i]) {
+ result.begin = i + 1;
+ begin_matched = true;
+ } else {
+ /*intentionally left blank*/
+ }
+ }
+ }
+
+ for (int i = pos; i <= str_len - 1; ++i) {
+ for (int j = 0; j < delimiter_size;++j) {
+ if (delimiters[j] == str[i]) {
+ result.end = i - 1;
+ end_matched = true;
+ } else {
+ /*intentionally left blank*/
+ }
+ }
+ }
+
+ if (!begin_matched) {
+ result.begin = 0;
+ }
+
+ if (!end_matched) {
+ result.end = strlen(str) - 1;
+ }
+
+ return result;
+}
+
+size_t devi_rfind(char const * const str, char const * const substr) {
+ size_t str_len = get_str_len(str);
+ size_t substr_len = get_str_len(substr);
+ for (size_t i = str_len-1; i >=0 ; --i) {
+ if (substr[substr_len-1] != str[i]) {
+ continue;
+ } else {
+ bool matched = true;
+ for (int j = substr_len-1; j >= 0; --j) {
+ if (substr[j] == str[i - (substr_len - j -1)]) {
+ continue;
+ } else {
+ matched = false;
+ }
+ }
+ if (matched) return (i - substr_len + 1);
+ }
+ }
+
+ return -1;
+}
+
+size_t devi_lfind(char const * const str, char const * const substr) {
+ size_t str_len = get_str_len(str);
+ size_t substr_len = get_str_len(substr);
+ for (size_t i = 0; i < str_len; ++i) {
+ if (substr[0] != str[i]) {
+ continue;
+ } else {
+ bool matched = true;
+ for (size_t j = 0; j < substr_len; ++j) {
+ if (i + j >= str_len) return -1;
+ if (substr[j] == str[i+j]) {
+ continue;
+ } else {
+ matched = false;
+ }
+ }
+ if (matched) return (i);
+ }
+ }
+
+ return -1;
+}
+
+void shell_completion(const char* buf, linenoiseCompletions* lc, size_t pos) {
+ if (0 != pos) {
+ word_pos_t word_pos = devi_find_middle_word(buf, ID_BREAKERS, NELEMS(ID_BREAKERS), pos - 1);
+
+ if (word_pos.begin == -1 || word_pos.end == -1) {
+ return;
+ }
+
+ char* last_word = malloc(word_pos.end - word_pos.begin + 2);
+ last_word[word_pos.end - word_pos.begin + 1] = '\0';
+ memcpy(last_word, &buf[word_pos.begin], word_pos.end - word_pos.begin + 1);
+ char* ln_matched;
+
+ // custom list completion candidates
+ for(int i=0; i < NELEMS(LUA_FUNCS); ++i) {
+ if ( 0 == devi_lfind(LUA_FUNCS[i], last_word)) {
+ ln_matched = malloc(strlen(buf) + strlen(LUA_FUNCS[i]) - strlen(last_word) + 1);
+ ln_matched[strlen(buf) + strlen(LUA_FUNCS[i]) - strlen(last_word)] = '\0';
+ memcpy(ln_matched, buf, word_pos.begin);
+ memcpy(&ln_matched[word_pos.begin], LUA_FUNCS[i], strlen(LUA_FUNCS[i]));
+
+ if (0 == (strlen(buf) - word_pos.end - 1)) {
+ /* No Op */
+ } else {
+ memcpy(&ln_matched[word_pos.begin + strlen(LUA_FUNCS[i])], &buf[pos], strlen(buf) - pos + 1);
+ }
+
+ linenoiseAddCompletion(lc, ln_matched, pos + strlen(LUA_FUNCS[i]) - strlen(last_word));
+ free(ln_matched);
+ }
+ }
+
+#if 0
+ // Lua global table completions
+ lua_pushglobaltable(ls);
+ lua_pushnil(ls);
+ while(0 != lua_next(ls, -2)) {
+ if ( 0 == devi_lfind(lua_tostring(ls, -2), last_word)) {
+ char* ss = lua_tostring(ls, -2);
+ ln_matched = malloc(strlen(buf) + strlen(ss) - strlen(last_word) + 1);
+ ln_matched[strlen(buf) + strlen(ss) - strlen(last_word)] = '\0';
+ memcpy(ln_matched, buf, word_pos.begin);
+ memcpy(&ln_matched[word_pos.begin], ss, strlen(ss));
+
+ if (0 == (strlen(buf) - word_pos.end - 1)) {
+ /* No Op */
+ } else {
+ memcpy(&ln_matched[word_pos.begin + strlen(ss)], &buf[pos], strlen(buf) - pos + 1);
+ }
+
+ linenoiseAddCompletion(lc, ln_matched, pos + strlen(ss) - strlen(last_word));
+ free(ln_matched);
+ }
+ lua_pop(ls, 1);
+ }
+ lua_pop(ls, 1);
+#endif
+
+ free(last_word);
+ }
+}
+
+char* shell_hint(const char* buf, int* color, int* bold) {
+ if (NULL != buf) {
+ *color = 35;
+ *bold = 0;
+ } else {
+ return "";
+ }
+
+ int last_word_index = devi_find_last_word(buf, ID_BREAKERS, NELEMS(ID_BREAKERS));
+ char* last_word = malloc(strlen(buf) - last_word_index+1);
+ last_word[strlen(buf) - last_word_index] = '\0';
+ memcpy(last_word, &buf[last_word_index], strlen(buf) - last_word_index);
+ char* ln_matched;
+ for(int i=0; i < NELEMS(LUA_FUNCS); ++i) {
+ size_t match_index = devi_lfind(LUA_FUNCS[i], last_word);
+ if (0 == match_index) {
+ ln_matched = malloc(strlen(LUA_FUNCS[i])-strlen(last_word)+1);
+ ln_matched[strlen(LUA_FUNCS[i]) - strlen(last_word)] = '\0';
+ memcpy(ln_matched, &LUA_FUNCS[i][match_index+strlen(last_word)], strlen(LUA_FUNCS[i]) - strlen(last_word));
+ free(last_word);
+ return ln_matched;
+ }
+ }
+
+#if 0
+ lua_pushglobaltable(ls);
+ lua_pushnil(ls);
+ while(0 != lua_next(ls, -2)) {
+ size_t match_index = devi_lfind(lua_tostring(ls, -2), last_word);
+ if (0 == match_index) {
+ ln_matched = malloc(strlen(lua_tostring(ls, -2))-strlen(last_word)+1);
+ ln_matched[strlen(lua_tostring(ls, -2)) - strlen(last_word)] = '\0';
+ memcpy(ln_matched, &lua_tostring(ls, -2)[match_index+strlen(last_word)], strlen(lua_tostring(ls, -2)) - strlen(last_word));
+ free(last_word);
+ return ln_matched;
+ }
+ lua_pop(ls, 1);
+ }
+ lua_pop(ls, 1);
+#endif
+
+ free(last_word);
+ return NULL;
+}
+/**********************************************************************************************************************/
+/*last line intentionally left blank*/
+