Mercurial > vim
comparison src/autocmd.c @ 28917:c5862dfaf0bd v8.2.4981
patch 8.2.4981: it is not possible to manipulate autocommands
Commit: https://github.com/vim/vim/commit/1755a91851f7022fdd3eecfbd2cc0b508a2f2a8f
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Thu May 19 10:31:47 2022 +0100
patch 8.2.4981: it is not possible to manipulate autocommands
Problem: It is not possible to manipulate autocommands.
Solution: Add functions to add, get and set autocommands. (Yegappan
Lakshmanan, closes #10291)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 19 May 2022 11:45:05 +0200 |
parents | d770568e6c98 |
children | 3c3bdb8069f5 |
comparison
equal
deleted
inserted
replaced
28916:40a5b3396eb4 | 28917:c5862dfaf0bd |
---|---|
2560 char_u * | 2560 char_u * |
2561 get_augroup_name(expand_T *xp UNUSED, int idx) | 2561 get_augroup_name(expand_T *xp UNUSED, int idx) |
2562 { | 2562 { |
2563 if (idx == augroups.ga_len) // add "END" add the end | 2563 if (idx == augroups.ga_len) // add "END" add the end |
2564 return (char_u *)"END"; | 2564 return (char_u *)"END"; |
2565 if (idx >= augroups.ga_len) // end of list | 2565 if (idx < 0 || idx >= augroups.ga_len) // end of list |
2566 return NULL; | 2566 return NULL; |
2567 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) | 2567 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) |
2568 // skip deleted entries | 2568 // skip deleted entries |
2569 return (char_u *)""; | 2569 return (char_u *)""; |
2570 return AUGROUP_NAME(idx); // return a name | 2570 return AUGROUP_NAME(idx); // return a name |
2745 | 2745 |
2746 theend: | 2746 theend: |
2747 vim_free(arg_save); | 2747 vim_free(arg_save); |
2748 return retval; | 2748 return retval; |
2749 } | 2749 } |
2750 #endif | 2750 |
2751 /* | |
2752 * autocmd_add() and autocmd_delete() functions | |
2753 */ | |
2754 static void | |
2755 autocmd_add_or_delete(typval_T *argvars, typval_T *rettv, int delete) | |
2756 { | |
2757 list_T *event_list; | |
2758 listitem_T *li; | |
2759 dict_T *event_dict; | |
2760 char_u *event_name = NULL; | |
2761 event_T event; | |
2762 char_u *group_name = NULL; | |
2763 int group; | |
2764 char_u *pat = NULL; | |
2765 char_u *cmd = NULL; | |
2766 char_u *end; | |
2767 int once; | |
2768 int nested; | |
2769 int retval = VVAL_TRUE; | |
2770 int save_augroup = current_augroup; | |
2771 | |
2772 rettv->v_type = VAR_BOOL; | |
2773 rettv->vval.v_number = VVAL_FALSE; | |
2774 | |
2775 if (check_for_list_arg(argvars, 0) == FAIL) | |
2776 return; | |
2777 | |
2778 event_list = argvars[0].vval.v_list; | |
2779 if (event_list == NULL) | |
2780 return; | |
2781 | |
2782 FOR_ALL_LIST_ITEMS(event_list, li) | |
2783 { | |
2784 VIM_CLEAR(event_name); | |
2785 VIM_CLEAR(group_name); | |
2786 VIM_CLEAR(pat); | |
2787 VIM_CLEAR(cmd); | |
2788 | |
2789 if (li->li_tv.v_type != VAR_DICT) | |
2790 continue; | |
2791 | |
2792 event_dict = li->li_tv.vval.v_dict; | |
2793 if (event_dict == NULL) | |
2794 continue; | |
2795 | |
2796 event_name = dict_get_string(event_dict, (char_u *)"event", TRUE); | |
2797 if (event_name == NULL) | |
2798 { | |
2799 if (delete) | |
2800 // if the event name is not specified, delete all the events | |
2801 event = NUM_EVENTS; | |
2802 else | |
2803 continue; | |
2804 } | |
2805 else | |
2806 { | |
2807 if (delete && event_name[0] == '*' && event_name[1] == NUL) | |
2808 // if the event name is '*', delete all the events | |
2809 event = NUM_EVENTS; | |
2810 else | |
2811 { | |
2812 event = event_name2nr(event_name, &end); | |
2813 if (event == NUM_EVENTS) | |
2814 { | |
2815 semsg(_(e_no_such_event_str), event_name); | |
2816 retval = VVAL_FALSE; | |
2817 break; | |
2818 } | |
2819 } | |
2820 } | |
2821 | |
2822 group_name = dict_get_string(event_dict, (char_u *)"group", TRUE); | |
2823 if (group_name == NULL || *group_name == NUL) | |
2824 // if the autocmd group name is not specified, then use the current | |
2825 // autocmd group | |
2826 group = current_augroup; | |
2827 else | |
2828 { | |
2829 group = au_find_group(group_name); | |
2830 if (group == AUGROUP_ERROR) | |
2831 { | |
2832 if (delete) | |
2833 { | |
2834 semsg(_(e_no_such_group_str), group_name); | |
2835 retval = VVAL_FALSE; | |
2836 break; | |
2837 } | |
2838 // group is not found, create it now | |
2839 group = au_new_group(group_name); | |
2840 if (group == AUGROUP_ERROR) | |
2841 { | |
2842 semsg(_(e_no_such_group_str), group_name); | |
2843 retval = VVAL_FALSE; | |
2844 break; | |
2845 } | |
2846 | |
2847 current_augroup = group; | |
2848 } | |
2849 } | |
2850 | |
2851 // if a buffer number is specified, then generate a pattern of the form | |
2852 // "<buffer=n>. Otherwise, use the pattern supplied by the user. | |
2853 if (dict_has_key(event_dict, "bufnr")) | |
2854 { | |
2855 varnumber_T bnum; | |
2856 | |
2857 bnum = dict_get_number_def(event_dict, (char_u *)"bufnr", -1); | |
2858 if (bnum == -1) | |
2859 continue; | |
2860 | |
2861 pat = alloc(128 + 1); | |
2862 if (pat == NULL) | |
2863 continue; | |
2864 vim_snprintf((char *)pat, 128, "<buffer=%d>", (int)bnum); | |
2865 } | |
2866 else | |
2867 { | |
2868 pat = dict_get_string(event_dict, (char_u *)"pattern", TRUE); | |
2869 if (pat == NULL) | |
2870 { | |
2871 if (delete) | |
2872 pat = vim_strsave((char_u *)""); | |
2873 else | |
2874 continue; | |
2875 } | |
2876 } | |
2877 | |
2878 once = dict_get_bool(event_dict, (char_u *)"once", FALSE); | |
2879 nested = dict_get_bool(event_dict, (char_u *)"nested", FALSE); | |
2880 | |
2881 cmd = dict_get_string(event_dict, (char_u *)"cmd", TRUE); | |
2882 if (cmd == NULL) | |
2883 { | |
2884 if (delete) | |
2885 cmd = vim_strsave((char_u *)""); | |
2886 else | |
2887 continue; | |
2888 } | |
2889 | |
2890 if (event == NUM_EVENTS) | |
2891 { | |
2892 // event is '*', apply for all the events | |
2893 for (event = (event_T)0; (int)event < NUM_EVENTS; | |
2894 event = (event_T)((int)event + 1)) | |
2895 { | |
2896 if (do_autocmd_event(event, pat, once, nested, cmd, delete, | |
2897 group, 0) == FAIL) | |
2898 { | |
2899 retval = VVAL_FALSE; | |
2900 break; | |
2901 } | |
2902 } | |
2903 } | |
2904 else | |
2905 { | |
2906 if (do_autocmd_event(event, pat, once, nested, cmd, delete, group, | |
2907 0) == FAIL) | |
2908 { | |
2909 retval = VVAL_FALSE; | |
2910 break; | |
2911 } | |
2912 } | |
2913 | |
2914 // if only the autocmd group name is specified for delete and the | |
2915 // autocmd event, pattern and cmd are not specified, then delete the | |
2916 // autocmd group. | |
2917 if (delete && group_name != NULL && | |
2918 (event_name == NULL || event_name[0] == NUL) | |
2919 && (pat == NULL || pat[0] == NUL) | |
2920 && (cmd == NULL || cmd[0] == NUL)) | |
2921 au_del_group(group_name); | |
2922 } | |
2923 | |
2924 VIM_CLEAR(event_name); | |
2925 VIM_CLEAR(group_name); | |
2926 VIM_CLEAR(pat); | |
2927 VIM_CLEAR(cmd); | |
2928 | |
2929 current_augroup = save_augroup; | |
2930 rettv->vval.v_number = retval; | |
2931 } | |
2932 | |
2933 /* | |
2934 * autocmd_add() function | |
2935 */ | |
2936 void | |
2937 f_autocmd_add(typval_T *argvars, typval_T *rettv) | |
2938 { | |
2939 autocmd_add_or_delete(argvars, rettv, FALSE); | |
2940 } | |
2941 | |
2942 /* | |
2943 * autocmd_delete() function | |
2944 */ | |
2945 void | |
2946 f_autocmd_delete(typval_T *argvars, typval_T *rettv) | |
2947 { | |
2948 autocmd_add_or_delete(argvars, rettv, TRUE); | |
2949 } | |
2950 | |
2951 /* | |
2952 * autocmd_get() function | |
2953 * Returns a List of autocmds. | |
2954 */ | |
2955 void | |
2956 f_autocmd_get(typval_T *argvars, typval_T *rettv) | |
2957 { | |
2958 event_T event_arg = NUM_EVENTS; | |
2959 event_T event; | |
2960 AutoPat *ap; | |
2961 AutoCmd *ac; | |
2962 list_T *event_list; | |
2963 dict_T *event_dict; | |
2964 char_u *event_name = NULL; | |
2965 char_u *pat = NULL; | |
2966 char_u *name = NULL; | |
2967 int group = AUGROUP_ALL; | |
2968 | |
2969 if (check_for_opt_dict_arg(argvars, 0) == FAIL) | |
2970 return; | |
2971 | |
2972 if (argvars[0].v_type == VAR_DICT) | |
2973 { | |
2974 // return only the autocmds in the specified group | |
2975 if (dict_has_key(argvars[0].vval.v_dict, "group")) | |
2976 { | |
2977 name = dict_get_string(argvars[0].vval.v_dict, | |
2978 (char_u *)"group", TRUE); | |
2979 if (name == NULL) | |
2980 return; | |
2981 | |
2982 if (*name == NUL) | |
2983 group = AUGROUP_DEFAULT; | |
2984 else | |
2985 { | |
2986 group = au_find_group(name); | |
2987 if (group == AUGROUP_ERROR) | |
2988 { | |
2989 semsg(_(e_no_such_group_str), name); | |
2990 vim_free(name); | |
2991 return; | |
2992 } | |
2993 } | |
2994 vim_free(name); | |
2995 } | |
2996 | |
2997 // return only the autocmds for the specified event | |
2998 if (dict_has_key(argvars[0].vval.v_dict, "event")) | |
2999 { | |
3000 int i; | |
3001 | |
3002 name = dict_get_string(argvars[0].vval.v_dict, | |
3003 (char_u *)"event", TRUE); | |
3004 if (name == NULL) | |
3005 return; | |
3006 | |
3007 if (name[0] == '*' && name[1] == NUL) | |
3008 event_arg = NUM_EVENTS; | |
3009 else | |
3010 { | |
3011 for (i = 0; event_names[i].name != NULL; i++) | |
3012 if (STRICMP(event_names[i].name, name) == 0) | |
3013 break; | |
3014 if (event_names[i].name == NULL) | |
3015 { | |
3016 semsg(_(e_no_such_event_str), name); | |
3017 vim_free(name); | |
3018 return; | |
3019 } | |
3020 event_arg = event_names[i].event; | |
3021 } | |
3022 vim_free(name); | |
3023 } | |
3024 | |
3025 // return only the autocmds for the specified pattern | |
3026 if (dict_has_key(argvars[0].vval.v_dict, "pattern")) | |
3027 { | |
3028 pat = dict_get_string(argvars[0].vval.v_dict, | |
3029 (char_u *)"pattern", TRUE); | |
3030 if (pat == NULL) | |
3031 return; | |
3032 } | |
3033 } | |
3034 | |
3035 if (rettv_list_alloc(rettv) == FAIL) | |
3036 return; | |
3037 event_list = rettv->vval.v_list; | |
3038 | |
3039 // iterate through all the autocmd events | |
3040 for (event = (event_T)0; (int)event < NUM_EVENTS; | |
3041 event = (event_T)((int)event + 1)) | |
3042 { | |
3043 if (event_arg != NUM_EVENTS && event != event_arg) | |
3044 continue; | |
3045 | |
3046 event_name = event_nr2name(event); | |
3047 | |
3048 // iterate through all the patterns for this autocmd event | |
3049 FOR_ALL_AUTOCMD_PATTERNS(event, ap) | |
3050 { | |
3051 char_u *group_name; | |
3052 | |
3053 if (group != AUGROUP_ALL && group != ap->group) | |
3054 continue; | |
3055 | |
3056 if (pat != NULL && STRCMP(pat, ap->pat) != 0) | |
3057 continue; | |
3058 | |
3059 group_name = get_augroup_name(NULL, ap->group); | |
3060 | |
3061 // iterate through all the commands for this pattern and add one | |
3062 // item for each cmd. | |
3063 for (ac = ap->cmds; ac != NULL; ac = ac->next) | |
3064 { | |
3065 event_dict = dict_alloc(); | |
3066 if (event_dict == NULL) | |
3067 return; | |
3068 | |
3069 if (list_append_dict(event_list, event_dict) == FAIL) | |
3070 return; | |
3071 | |
3072 if (dict_add_string(event_dict, "event", event_name) == FAIL) | |
3073 return; | |
3074 | |
3075 if (dict_add_string(event_dict, "group", group_name == NULL | |
3076 ? (char_u *)"" : group_name) == FAIL) | |
3077 return; | |
3078 | |
3079 if (ap->buflocal_nr != 0) | |
3080 if (dict_add_number(event_dict, "bufnr", ap->buflocal_nr) | |
3081 == FAIL) | |
3082 return; | |
3083 | |
3084 if (dict_add_string(event_dict, "pattern", ap->pat) == FAIL) | |
3085 return; | |
3086 | |
3087 if (dict_add_string(event_dict, "cmd", ac->cmd) == FAIL) | |
3088 return; | |
3089 | |
3090 if (dict_add_bool(event_dict, "once", ac->once) == FAIL) | |
3091 return; | |
3092 if (dict_add_bool(event_dict, "nested", ac->nested) == FAIL) | |
3093 return; | |
3094 } | |
3095 } | |
3096 } | |
3097 | |
3098 vim_free(pat); | |
3099 } | |
3100 | |
3101 #endif |