diff options
Diffstat (limited to 'src/autocmd.c')
-rw-r--r-- | src/autocmd.c | 488 |
1 files changed, 0 insertions, 488 deletions
diff --git a/src/autocmd.c b/src/autocmd.c deleted file mode 100644 index e856a4c..0000000 --- a/src/autocmd.c +++ /dev/null @@ -1,488 +0,0 @@ -/** - * vimb - a webkit based vim like browser. - * - * Copyright (C) 2012-2015 Daniel Carl - * - * 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 http://www.gnu.org/licenses/. - */ - -#include "config.h" -#ifdef FEATURE_AUTOCMD -#include "autocmd.h" -#include "ascii.h" -#include "ex.h" -#include "util.h" -#include "completion.h" - -typedef struct { - guint bits; /* the bits identify the events the command applies to */ - char *excmd; /* ex command string to be run on matches event */ - char *pattern; /* list of patterns the uri is matched agains */ -} AutoCmd; - -typedef struct { - char *name; - GSList *cmds; -} AuGroup; - -static struct { - const char *name; - guint bits; -} events[] = { - {"*", 0x00ff}, - {"LoadProvisional", 0x0001}, - {"LoadCommited", 0x0002}, - {"LoadFirstLayout", 0x0004}, - {"LoadFinished", 0x0008}, - {"LoadFailed", 0x0010}, - {"DownloadStart", 0x0020}, - {"DownloadFinished", 0x0040}, - {"DownloadFailed", 0x0080}, -}; - -extern VbCore vb; - -static AuGroup *curgroup = NULL; -static GSList *groups = NULL; -static guint usedbits = 0; /* holds all used event bits */ - -static GSList *get_group(const char *name); -static guint get_event_bits(const char *name); -static void rebuild_used_bits(void); -static char *get_next_word(char **line); -static AuGroup *new_group(const char *name); -static void free_group(AuGroup *group); -static AutoCmd *new_autocmd(const char *excmd, const char *pattern); -static void free_autocmd(AutoCmd *cmd); - - -void autocmd_init(void) -{ - curgroup = new_group("end"); - groups = g_slist_prepend(groups, curgroup); -} - -void autocmd_cleanup(void) -{ - if (groups) { - g_slist_free_full(groups, (GDestroyNotify)free_group); - } -} - -/** - * Handle the :augroup {group} ex command. - */ -gboolean autocmd_augroup(char *name, gboolean delete) -{ - GSList *item; - - if (!*name) { - return false; - } - - /* check for group "end" that marks the default group */ - if (!strcmp(name, "end")) { - curgroup = (AuGroup*)groups->data; - return true; - } - - item = get_group(name); - - /* check if the group is going to be removed */ - if (delete) { - /* group does not exist - so do nothing */ - if (!item) { - return true; - } - if (curgroup == (AuGroup*)item->data) { - /* if the group to delete is the current - switch the the default - * group after removing it */ - curgroup = (AuGroup*)groups->data; - } - - /* now remove the group */ - free_group((AuGroup*)item->data); - groups = g_slist_delete_link(groups, item); - - /* there where autocmds remove - so recreate the usedbits */ - rebuild_used_bits(); - - return true; - } - - /* check if the group does already exists */ - if (item) { - /* if the group is found in the known groups use it as current */ - curgroup = (AuGroup*)item->data; - - return true; - } - - /* create a new group and use it as current */ - curgroup = new_group(name); - - /* append it to known groups */ - groups = g_slist_prepend(groups, curgroup); - - return true; -} - -/** - * Add or delete auto commands. - * - * :au[tocmd]! [group] {event} {pat} [nested] {cmd} - * group and nested flag are not supported at the moment. - */ -gboolean autocmd_add(char *name, gboolean delete) -{ - guint bits; - char *parse, *word, *pattern, *excmd; - GSList *item; - AuGroup *grp = NULL; - - parse = name; - - /* parse group name if it's there */ - word = get_next_word(&parse); - if (word) { - /* check if the word is a known group name */ - item = get_group(word); - if (item) { - grp = (AuGroup*)item->data; - - /* group is found - get the next word */ - word = get_next_word(&parse); - } - } - if (!grp) { - /* no group found - use the current one */ - grp = curgroup; - } - - /* parse event name - if none was matched run it for all events */ - if (word) { - bits = get_event_bits(word); - if (!bits) { - return false; - } - word = get_next_word(&parse); - } else { - bits = events[AU_ALL].bits; - } - - /* last word is the pattern - if not found use '*' */ - pattern = word ? word : "*"; - - /* the rest of the line becoes the ex command to run */ - if (parse && !*parse) { - parse = NULL; - } - excmd = parse; - - /* delete the autocmd if bang was given */ - if (delete) { - GSList *lc; - AutoCmd *cmd; - gboolean removed = false; - - /* check if the group does already exists */ - for (lc = grp->cmds; lc; lc = lc->next) { - cmd = (AutoCmd*)lc->data; - /* if not bits match - skip the command */ - if (!(cmd->bits & bits)) { - continue; - } - /* skip if pattern does not match - we check the pattern against - * another pattern */ - if (!util_wildmatch(pattern, cmd->pattern)) { - continue; - } - /* remove the bits from the item */ - cmd->bits &= ~bits; - - /* if the command has no matching events - remove it */ - grp->cmds = g_slist_delete_link(grp->cmds, lc); - free_autocmd(cmd); - - removed = true; - } - - /* if ther was at least one command removed - rebuilt the used bits */ - if (removed) { - rebuild_used_bits(); - } - - return true; - } - - /* add the new autocmd */ - if (excmd && grp) { - AutoCmd *cmd = new_autocmd(excmd, pattern); - cmd->bits = bits; - - /* add the new autocmd to the group */ - grp->cmds = g_slist_append(grp->cmds, cmd); - - /* merge the autocmd bits into the used bits */ - usedbits |= cmd->bits; - } - - return true; -} - -/** - * Run named auto command. - */ -gboolean autocmd_run(AuEvent event, const char *uri, const char *group) -{ - GSList *lg, *lc; - AuGroup *grp; - AutoCmd *cmd; - guint bits = events[event].bits; - - /* if there is no autocmd for this event - skip here */ - if (!(usedbits & bits)) { - return true; - } - - /* loop over the groups and find matching commands */ - for (lg = groups; lg; lg = lg->next) { - grp = lg->data; - /* if a group was given - skip all none matching groupes */ - if (group && strcmp(group, grp->name)) { - continue; - } - /* test each command in group */ - for (lc = grp->cmds; lc; lc = lc->next) { - cmd = lc->data; - /* skip if this dos not match the event bits */ - if (!(bits & cmd->bits)) { - continue; - } - /* check pattern only if uri was given */ - /* skip if pattern does not match */ - if (uri && !util_wildmatch(cmd->pattern, uri)) { - continue; - } - /* run the command */ - /* TODO shoult the result be tested for RESULT_COMPLETE? */ - /* run command and make sure it's not writte to command history */ - ex_run_string(cmd->excmd, false); - } - } - - return true; -} - -gboolean autocmd_fill_group_completion(GtkListStore *store, const char *input) -{ - GSList *lg; - gboolean found = false; - GtkTreeIter iter; - - if (!input || !*input) { - for (lg = groups; lg; lg = lg->next) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, ((AuGroup*)lg->data)->name, -1); - found = true; - } - } else { - for (lg = groups; lg; lg = lg->next) { - char *value = ((AuGroup*)lg->data)->name; - if (g_str_has_prefix(value, input)) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, value, -1); - found = true; - } - } - } - - return found; -} - -gboolean autocmd_fill_event_completion(GtkListStore *store, const char *input) -{ - int i; - const char *value; - gboolean found = false; - GtkTreeIter iter; - - if (!input || !*input) { - for (i = 0; i < LENGTH(events); i++) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, events[i].name, -1); - found = true; - } - } else { - for (i = 0; i < LENGTH(events); i++) { - value = events[i].name; - if (g_str_has_prefix(value, input)) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, value, -1); - found = true; - } - } - } - - return found; -} - -/** - * Get the augroup by it's name. - */ -static GSList *get_group(const char *name) -{ - GSList *lg; - AuGroup *grp; - - for (lg = groups; lg; lg = lg->next) { - grp = lg->data; - if (!strcmp(grp->name, name)) { - return lg; - } - } - - return NULL; -} - -static guint get_event_bits(const char *name) -{ - int result = 0; - - while (*name) { - int i, len; - for (i = 0; i < LENGTH(events); i++) { - /* we count the chars that given name has in common with the - * current processed event */ - len = 0; - while (name[len] && events[i].name[len] && name[len] == events[i].name[len]) { - len++; - } - - /* check if the matching chars built a full word match */ - if (events[i].name[len] == '\0' - && (name[len] == '\0' || name[len] == ',') - ) { - /* add the bits to the result */ - result |= events[i].bits; - - /* move pointer after the match and skip possible ',' */ - name += len; - if (*name == ',') { - name++; - } - break; - } - } - - /* check if the end was reached without a match */ - if (i >= LENGTH(events)) { - /* is this the right place to write the error */ - vb_echo(VB_MSG_ERROR, true, "Bad autocmd event name: %s", name); - return 0; - } - } - - return result; -} - -/** - * Rebuild the usedbits from scratch. - * Save all used autocmd event bits in the bitmap. - */ -static void rebuild_used_bits(void) -{ - GSList *lc, *lg; - AuGroup *grp; - - /* clear the current set bits */ - usedbits = 0; - /* loop over the groups */ - for (lg = groups; lg; lg = lg->next) { - grp = (AuGroup*)lg->data; - - /* merge the used event bints into the bitmap */ - for (lc = grp->cmds; lc; lc = lc->next) { - usedbits |= ((AutoCmd*)lc->data)->bits; - } - } -} - -/** - * Get the next word from given line. - * Given line pointer is set past the word and and a 0-byte is added there. - */ -static char *get_next_word(char **line) -{ - char *word; - - if (!*line || !**line) { - return NULL; - } - - /* remember where the word starts */ - word = *line; - - /* move pointer to the end of the word or of the line */ - while (**line && !VB_IS_SPACE(**line)) { - (*line)++; - } - - /* end the word */ - if (**line) { - *(*line)++ = '\0'; - } - - /* skip trailing whitespace */ - while (VB_IS_SPACE(**line)) { - (*line)++; - } - - return word; -} - -static AuGroup *new_group(const char *name) -{ - AuGroup *new = g_slice_new(AuGroup); - new->name = g_strdup(name); - new->cmds = NULL; - - return new; -} - -static void free_group(AuGroup *group) -{ - g_free(group->name); - if (group->cmds) { - g_slist_free_full(group->cmds, (GDestroyNotify)free_autocmd); - } - g_slice_free(AuGroup, group); -} - -static AutoCmd *new_autocmd(const char *excmd, const char *pattern) -{ - AutoCmd *new = g_slice_new(AutoCmd); - new->excmd = g_strdup(excmd); - new->pattern = g_strdup(pattern); - return new; -} - -static void free_autocmd(AutoCmd *cmd) -{ - g_free(cmd->excmd); - g_free(cmd->pattern); - g_slice_free(AutoCmd, cmd); -} - -#endif |