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