Mercurial > vim
comparison src/eval.c @ 8174:f2286ff0c102 v7.4.1380
commit https://github.com/vim/vim/commit/ee1cffc07a42441924c5353af7fd7ab6e97e5aae
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Feb 21 19:14:41 2016 +0100
patch 7.4.1380
Problem: The job exit callback is not implemented.
Solution: Add the "exit-cb" option.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 21 Feb 2016 19:15:04 +0100 |
parents | a0ffb1f3dedc |
children | e77efd7a7dad |
comparison
equal
deleted
inserted
replaced
8173:8f9a62af9212 | 8174:f2286ff0c102 |
---|---|
7772 first_job = job->jv_next; | 7772 first_job = job->jv_next; |
7773 else | 7773 else |
7774 job->jv_prev->jv_next = job->jv_next; | 7774 job->jv_prev->jv_next = job->jv_next; |
7775 | 7775 |
7776 vim_free(job->jv_stoponexit); | 7776 vim_free(job->jv_stoponexit); |
7777 vim_free(job->jv_exit_cb); | |
7777 vim_free(job); | 7778 vim_free(job); |
7778 } | 7779 } |
7779 | 7780 |
7780 static void | 7781 static void |
7781 job_unref(job_T *job) | 7782 job_unref(job_T *job) |
7782 { | 7783 { |
7783 if (job != NULL && --job->jv_refcount <= 0) | 7784 if (job != NULL && --job->jv_refcount <= 0) |
7784 job_free(job); | 7785 { |
7786 /* Do not free the job when it has not ended yet and there is a | |
7787 * "stoponexit" flag or an exit callback. */ | |
7788 if (job->jv_status != JOB_STARTED | |
7789 || (job->jv_stoponexit == NULL && job->jv_exit_cb == NULL)) | |
7790 job_free(job); | |
7791 } | |
7785 } | 7792 } |
7786 | 7793 |
7787 /* | 7794 /* |
7788 * Allocate a job. Sets the refcount to one and sets options default. | 7795 * Allocate a job. Sets the refcount to one and sets options default. |
7789 */ | 7796 */ |
7817 if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL) | 7824 if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL) |
7818 job->jv_stoponexit = NULL; | 7825 job->jv_stoponexit = NULL; |
7819 else | 7826 else |
7820 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit); | 7827 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit); |
7821 } | 7828 } |
7829 if (opt->jo_set & JO_EXIT_CB) | |
7830 { | |
7831 vim_free(job->jv_exit_cb); | |
7832 if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL) | |
7833 job->jv_exit_cb = NULL; | |
7834 else | |
7835 job->jv_exit_cb = vim_strsave(opt->jo_exit_cb); | |
7836 } | |
7822 } | 7837 } |
7823 | 7838 |
7824 /* | 7839 /* |
7825 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag. | 7840 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag. |
7826 */ | 7841 */ |
7828 job_stop_on_exit() | 7843 job_stop_on_exit() |
7829 { | 7844 { |
7830 job_T *job; | 7845 job_T *job; |
7831 | 7846 |
7832 for (job = first_job; job != NULL; job = job->jv_next) | 7847 for (job = first_job; job != NULL; job = job->jv_next) |
7833 if (job->jv_stoponexit != NULL && *job->jv_stoponexit != NUL) | 7848 if (job->jv_status == JOB_STARTED && job->jv_stoponexit != NULL) |
7834 mch_stop_job(job, job->jv_stoponexit); | 7849 mch_stop_job(job, job->jv_stoponexit); |
7835 } | 7850 } |
7836 #endif | 7851 #endif |
7837 | 7852 |
7838 static char * | 7853 static char * |
10028 break; | 10043 break; |
10029 opt->jo_set |= JO_OUT_CALLBACK; | 10044 opt->jo_set |= JO_OUT_CALLBACK; |
10030 opt->jo_out_cb = get_callback(item); | 10045 opt->jo_out_cb = get_callback(item); |
10031 if (opt->jo_out_cb == NULL) | 10046 if (opt->jo_out_cb == NULL) |
10032 { | 10047 { |
10033 EMSG2(_(e_invarg2), "out-db"); | 10048 EMSG2(_(e_invarg2), "out-cb"); |
10034 return FAIL; | 10049 return FAIL; |
10035 } | 10050 } |
10036 } | 10051 } |
10037 else if (STRCMP(hi->hi_key, "err-cb") == 0) | 10052 else if (STRCMP(hi->hi_key, "err-cb") == 0) |
10038 { | 10053 { |
10103 opt->jo_stoponexit = get_tv_string_buf_chk(item, | 10118 opt->jo_stoponexit = get_tv_string_buf_chk(item, |
10104 opt->jo_soe_buf); | 10119 opt->jo_soe_buf); |
10105 if (opt->jo_stoponexit == NULL) | 10120 if (opt->jo_stoponexit == NULL) |
10106 { | 10121 { |
10107 EMSG2(_(e_invarg2), "stoponexit"); | 10122 EMSG2(_(e_invarg2), "stoponexit"); |
10123 return FAIL; | |
10124 } | |
10125 } | |
10126 else if (STRCMP(hi->hi_key, "exit-cb") == 0) | |
10127 { | |
10128 if (!(supported & JO_EXIT_CB)) | |
10129 break; | |
10130 opt->jo_set |= JO_EXIT_CB; | |
10131 opt->jo_exit_cb = get_tv_string_buf_chk(item, opt->jo_ecb_buf); | |
10132 if (opt->jo_ecb_buf == NULL) | |
10133 { | |
10134 EMSG2(_(e_invarg2), "exit-cb"); | |
10108 return FAIL; | 10135 return FAIL; |
10109 } | 10136 } |
10110 } | 10137 } |
10111 else | 10138 else |
10112 break; | 10139 break; |
14769 f_items(typval_T *argvars, typval_T *rettv) | 14796 f_items(typval_T *argvars, typval_T *rettv) |
14770 { | 14797 { |
14771 dict_list(argvars, rettv, 2); | 14798 dict_list(argvars, rettv, 2); |
14772 } | 14799 } |
14773 | 14800 |
14774 #ifdef FEAT_JOB | 14801 #if defined(FEAT_JOB) || defined(PROTO) |
14775 /* | 14802 /* |
14776 * Get the job from the argument. | 14803 * Get the job from the argument. |
14777 * Returns NULL if the job is invalid. | 14804 * Returns NULL if the job is invalid. |
14778 */ | 14805 */ |
14779 static job_T * | 14806 static job_T * |
14822 jobopt_T opt; | 14849 jobopt_T opt; |
14823 | 14850 |
14824 if (job == NULL) | 14851 if (job == NULL) |
14825 return; | 14852 return; |
14826 clear_job_options(&opt); | 14853 clear_job_options(&opt); |
14827 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT) == FAIL) | 14854 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT + JO_EXIT_CB) == FAIL) |
14828 return; | 14855 return; |
14829 job_set_options(job, &opt); | 14856 job_set_options(job, &opt); |
14830 } | 14857 } |
14831 | 14858 |
14832 /* | 14859 /* |
14856 | 14883 |
14857 /* Default mode is NL. */ | 14884 /* Default mode is NL. */ |
14858 clear_job_options(&opt); | 14885 clear_job_options(&opt); |
14859 opt.jo_mode = MODE_NL; | 14886 opt.jo_mode = MODE_NL; |
14860 if (get_job_options(&argvars[1], &opt, | 14887 if (get_job_options(&argvars[1], &opt, |
14861 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT) == FAIL) | 14888 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL |
14889 + JO_STOPONEXIT + JO_EXIT_CB) == FAIL) | |
14862 return; | 14890 return; |
14863 job_set_options(job, &opt); | 14891 job_set_options(job, &opt); |
14864 | 14892 |
14865 #ifndef USE_ARGV | 14893 #ifndef USE_ARGV |
14866 ga_init2(&ga, (int)sizeof(char*), 20); | 14894 ga_init2(&ga, (int)sizeof(char*), 20); |
14957 vim_free(ga.ga_data); | 14985 vim_free(ga.ga_data); |
14958 #endif | 14986 #endif |
14959 } | 14987 } |
14960 | 14988 |
14961 /* | 14989 /* |
14990 * Get the status of "job" and invoke the exit callback when needed. | |
14991 * The returned string is not allocated. | |
14992 */ | |
14993 static char * | |
14994 job_status(job_T *job) | |
14995 { | |
14996 char *result; | |
14997 | |
14998 if (job->jv_status == JOB_ENDED) | |
14999 /* No need to check, dead is dead. */ | |
15000 result = "dead"; | |
15001 else if (job->jv_status == JOB_FAILED) | |
15002 result = "fail"; | |
15003 else | |
15004 { | |
15005 result = mch_job_status(job); | |
15006 # ifdef FEAT_CHANNEL | |
15007 if (job->jv_status == JOB_ENDED) | |
15008 ch_log(job->jv_channel, "Job ended"); | |
15009 # endif | |
15010 if (job->jv_status == JOB_ENDED && job->jv_exit_cb != NULL) | |
15011 { | |
15012 typval_T argv[3]; | |
15013 typval_T rettv; | |
15014 int dummy; | |
15015 | |
15016 /* invoke the exit callback */ | |
15017 argv[0].v_type = VAR_JOB; | |
15018 argv[0].vval.v_job = job; | |
15019 argv[1].v_type = VAR_NUMBER; | |
15020 argv[1].vval.v_number = job->jv_exitval; | |
15021 call_func(job->jv_exit_cb, (int)STRLEN(job->jv_exit_cb), | |
15022 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL); | |
15023 clear_tv(&rettv); | |
15024 } | |
15025 if (job->jv_status == JOB_ENDED && job->jv_refcount == 0) | |
15026 { | |
15027 /* The job already was unreferenced, now that it ended it can be | |
15028 * freed. Careful: caller must not use "job" after this! */ | |
15029 job_free(job); | |
15030 } | |
15031 } | |
15032 return result; | |
15033 } | |
15034 | |
15035 /* | |
15036 * Called once in a while: check if any jobs with an "exit-cb" have ended. | |
15037 */ | |
15038 void | |
15039 job_check_ended() | |
15040 { | |
15041 static time_t last_check = 0; | |
15042 time_t now; | |
15043 job_T *job; | |
15044 job_T *next; | |
15045 | |
15046 /* Only do this once in 10 seconds. */ | |
15047 now = time(NULL); | |
15048 if (last_check + 10 < now) | |
15049 { | |
15050 last_check = now; | |
15051 for (job = first_job; job != NULL; job = next) | |
15052 { | |
15053 next = job->jv_next; | |
15054 if (job->jv_status == JOB_STARTED && job->jv_exit_cb != NULL) | |
15055 job_status(job); /* may free "job" */ | |
15056 } | |
15057 } | |
15058 } | |
15059 | |
15060 /* | |
14962 * "job_status()" function | 15061 * "job_status()" function |
14963 */ | 15062 */ |
14964 static void | 15063 static void |
14965 f_job_status(typval_T *argvars, typval_T *rettv) | 15064 f_job_status(typval_T *argvars, typval_T *rettv) |
14966 { | 15065 { |
14967 job_T *job = get_job_arg(&argvars[0]); | 15066 job_T *job = get_job_arg(&argvars[0]); |
14968 char *result; | 15067 char *result; |
14969 | 15068 |
14970 if (job != NULL) | 15069 if (job != NULL) |
14971 { | 15070 { |
14972 if (job->jv_status == JOB_ENDED) | 15071 result = job_status(job); |
14973 /* No need to check, dead is dead. */ | |
14974 result = "dead"; | |
14975 else if (job->jv_status == JOB_FAILED) | |
14976 result = "fail"; | |
14977 else | |
14978 result = mch_job_status(job); | |
14979 rettv->v_type = VAR_STRING; | 15072 rettv->v_type = VAR_STRING; |
14980 rettv->vval.v_string = vim_strsave((char_u *)result); | 15073 rettv->vval.v_string = vim_strsave((char_u *)result); |
14981 } | 15074 } |
14982 } | 15075 } |
14983 | 15076 |
22855 break; | 22948 break; |
22856 #endif | 22949 #endif |
22857 case VAR_JOB: | 22950 case VAR_JOB: |
22858 #ifdef FEAT_JOB | 22951 #ifdef FEAT_JOB |
22859 to->vval.v_job = from->vval.v_job; | 22952 to->vval.v_job = from->vval.v_job; |
22860 ++to->vval.v_job->jv_refcount; | 22953 if (to->vval.v_job != NULL) |
22954 ++to->vval.v_job->jv_refcount; | |
22861 break; | 22955 break; |
22862 #endif | 22956 #endif |
22863 case VAR_CHANNEL: | 22957 case VAR_CHANNEL: |
22864 #ifdef FEAT_CHANNEL | 22958 #ifdef FEAT_CHANNEL |
22865 to->vval.v_channel = from->vval.v_channel; | 22959 to->vval.v_channel = from->vval.v_channel; |