/* * autocompleters.c * vim: expandtab:ts=4:sts=4:sw=4 * * Copyright (C) 2012 - 2019 James Booth * * SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception */ #include "config.h" #include #include #include "tools/autocomplete.h" #include "command/cmd_ac.h" static GHashTable* plugin_to_acs; static GHashTable* plugin_to_filepath_acs; static void _free_autocompleters(GHashTable* key_to_ac) { g_hash_table_destroy(key_to_ac); } static void _free_filepath_autocompleters(GHashTable* prefixes) { g_hash_table_destroy(prefixes); } void autocompleters_init(void) { plugin_to_acs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_autocompleters); plugin_to_filepath_acs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_filepath_autocompleters); } void autocompleters_add(const char* const plugin_name, const char* key, char** items) { GHashTable* key_to_ac = g_hash_table_lookup(plugin_to_acs, plugin_name); if (key_to_ac) { if (g_hash_table_contains(key_to_ac, key)) { Autocomplete existing_ac = g_hash_table_lookup(key_to_ac, key); autocomplete_add_all(existing_ac, items); } else { Autocomplete new_ac = autocomplete_new(); autocomplete_add_all(new_ac, items); g_hash_table_insert(key_to_ac, g_strdup(key), new_ac); } } else { key_to_ac = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)autocomplete_free); Autocomplete new_ac = autocomplete_new(); autocomplete_add_all(new_ac, items); g_hash_table_insert(key_to_ac, g_strdup(key), new_ac); g_hash_table_insert(plugin_to_acs, g_strdup(plugin_name), key_to_ac); } } void autocompleters_remove(const char* const plugin_name, const char* key, char** items) { GHashTable* key_to_ac = g_hash_table_lookup(plugin_to_acs, plugin_name); if (!key_to_ac) { return; } if (!g_hash_table_contains(key_to_ac, key)) { return; } Autocomplete ac = g_hash_table_lookup(key_to_ac, key); autocomplete_remove_all(ac, items); } void autocompleters_clear(const char* const plugin_name, const char* key) { GHashTable* key_to_ac = g_hash_table_lookup(plugin_to_acs, plugin_name); if (!key_to_ac) { return; } if (!g_hash_table_contains(key_to_ac, key)) { return; } Autocomplete ac = g_hash_table_lookup(key_to_ac, key); autocomplete_clear(ac); } void autocompleters_filepath_add(const char* const plugin_name, const char* prefix) { GHashTable* prefixes = g_hash_table_lookup(plugin_to_filepath_acs, plugin_name); if (prefixes) { g_hash_table_add(prefixes, g_strdup(prefix)); } else { prefixes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); g_hash_table_add(prefixes, g_strdup(prefix)); g_hash_table_insert(plugin_to_filepath_acs, g_strdup(plugin_name), prefixes); } } char* autocompleters_complete(const char* const input, gboolean previous) { char* result = NULL; GList* ac_hashes = g_hash_table_get_values(plugin_to_acs); GList* curr_hash = ac_hashes; while (curr_hash) { GHashTable* key_to_ac = curr_hash->data; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, key_to_ac); while (g_hash_table_iter_next(&iter, &key, &value)) { result = autocomplete_param_with_ac(input, key, value, TRUE, previous); if (result) { g_list_free(ac_hashes); return result; } } curr_hash = g_list_next(curr_hash); } g_list_free(ac_hashes); GList* filepath_hashes = g_hash_table_get_values(plugin_to_filepath_acs); curr_hash = filepath_hashes; while (curr_hash) { GHashTable* prefixes_hash = curr_hash->data; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, prefixes_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { char* prefix = (char*)key; if (g_str_has_prefix(input, prefix)) { result = cmd_ac_complete_filepath(input, prefix, previous); if (result) { g_list_free(filepath_hashes); return result; } } } curr_hash = g_list_next(curr_hash); } g_list_free(filepath_hashes); return NULL; } void autocompleters_reset(void) { GList* ac_hashes = g_hash_table_get_values(plugin_to_acs); GList* curr_hash = ac_hashes; while (curr_hash) { GList* acs = g_hash_table_get_values(curr_hash->data); GList* curr = acs; while (curr) { autocomplete_reset(curr->data); curr = g_list_next(curr); } g_list_free(acs); curr_hash = g_list_next(curr_hash); } g_list_free(ac_hashes); } void autocompleters_destroy(void) { g_hash_table_destroy(plugin_to_acs); g_hash_table_destroy(plugin_to_filepath_acs); plugin_to_acs = NULL; plugin_to_filepath_acs = NULL; }