@@ -109,6 +109,7 @@ struct terminal_S {
109109#define TL_FINISH_OPEN 'o' /* ++open */
110110 char_u * tl_opencmd ;
111111 char_u * tl_eof_chars ;
112+ char_u * tl_api ; // prefix for terminal API function
112113
113114 char_u * tl_arg0_cmd ; // To format the status bar
114115
@@ -641,6 +642,11 @@ term_start(
641642 term -> tl_kill = vim_strnsave (opt -> jo_term_kill , p - opt -> jo_term_kill );
642643 }
643644
645+ if (opt -> jo_term_api != NULL )
646+ term -> tl_api = vim_strsave (opt -> jo_term_api );
647+ else
648+ term -> tl_api = vim_strsave ((char_u * )"Tapi_" );
649+
644650 /* System dependent: setup the vterm and maybe start the job in it. */
645651 if (argv == NULL
646652 && argvar -> v_type == VAR_STRING
@@ -708,44 +714,58 @@ ex_terminal(exarg_T *eap)
708714 cmd += 2 ;
709715 p = skiptowhite (cmd );
710716 ep = vim_strchr (cmd , '=' );
711- if (ep != NULL && ep < p )
712- p = ep ;
717+ if (ep != NULL )
718+ {
719+ if (ep < p )
720+ p = ep ;
721+ else
722+ ep = NULL ;
723+ }
713724
714- if ((int )(p - cmd ) == 5 && STRNICMP (cmd , "close" , 5 ) == 0 )
725+ # define OPTARG_HAS (name ) ((int)(p - cmd) == sizeof(name) - 1 \
726+ && STRNICMP(cmd, name, sizeof(name) - 1) == 0)
727+ if (OPTARG_HAS ("close" ))
715728 opt .jo_term_finish = 'c' ;
716- else if (( int )( p - cmd ) == 7 && STRNICMP ( cmd , "noclose" , 7 ) == 0 )
729+ else if (OPTARG_HAS ( "noclose" ) )
717730 opt .jo_term_finish = 'n' ;
718- else if (( int )( p - cmd ) == 4 && STRNICMP ( cmd , "open" , 4 ) == 0 )
731+ else if (OPTARG_HAS ( "open" ) )
719732 opt .jo_term_finish = 'o' ;
720- else if (( int )( p - cmd ) == 6 && STRNICMP ( cmd , "curwin" , 6 ) == 0 )
733+ else if (OPTARG_HAS ( "curwin" ) )
721734 opt .jo_curwin = 1 ;
722- else if (( int )( p - cmd ) == 6 && STRNICMP ( cmd , "hidden" , 6 ) == 0 )
735+ else if (OPTARG_HAS ( "hidden" ) )
723736 opt .jo_hidden = 1 ;
724- else if (( int )( p - cmd ) == 9 && STRNICMP ( cmd , "norestore" , 9 ) == 0 )
737+ else if (OPTARG_HAS ( "norestore" ) )
725738 opt .jo_term_norestore = 1 ;
726- else if ((int )(p - cmd ) == 4 && STRNICMP (cmd , "kill" , 4 ) == 0
727- && ep != NULL )
739+ else if (OPTARG_HAS ("kill" ) && ep != NULL )
728740 {
729741 opt .jo_set2 |= JO2_TERM_KILL ;
730742 opt .jo_term_kill = ep + 1 ;
731743 p = skiptowhite (cmd );
732744 }
733- else if ((int )(p - cmd ) == 4 && STRNICMP (cmd , "rows" , 4 ) == 0
734- && ep != NULL && isdigit (ep [1 ]))
745+ else if (OPTARG_HAS ("api" ))
746+ {
747+ opt .jo_set2 |= JO2_TERM_API ;
748+ if (ep != NULL )
749+ {
750+ opt .jo_term_api = ep + 1 ;
751+ p = skiptowhite (cmd );
752+ }
753+ else
754+ opt .jo_term_api = NULL ;
755+ }
756+ else if (OPTARG_HAS ("rows" ) && ep != NULL && isdigit (ep [1 ]))
735757 {
736758 opt .jo_set2 |= JO2_TERM_ROWS ;
737759 opt .jo_term_rows = atoi ((char * )ep + 1 );
738760 p = skiptowhite (cmd );
739761 }
740- else if ((int )(p - cmd ) == 4 && STRNICMP (cmd , "cols" , 4 ) == 0
741- && ep != NULL && isdigit (ep [1 ]))
762+ else if (OPTARG_HAS ("cols" ) && ep != NULL && isdigit (ep [1 ]))
742763 {
743764 opt .jo_set2 |= JO2_TERM_COLS ;
744765 opt .jo_term_cols = atoi ((char * )ep + 1 );
745766 p = skiptowhite (cmd );
746767 }
747- else if ((int )(p - cmd ) == 3 && STRNICMP (cmd , "eof" , 3 ) == 0
748- && ep != NULL )
768+ else if (OPTARG_HAS ("eof" ) && ep != NULL )
749769 {
750770 char_u * buf = NULL ;
751771 char_u * keys ;
@@ -785,6 +805,7 @@ ex_terminal(exarg_T *eap)
785805 semsg (_ ("E181: Invalid attribute: %s" ), cmd );
786806 goto theend ;
787807 }
808+ # undef OPTARG_HAS
788809 cmd = skipwhite (p );
789810 }
790811 if (* cmd == NUL )
@@ -933,6 +954,7 @@ free_unused_terminals()
933954 free_scrollback (term );
934955
935956 term_free_vterm (term );
957+ vim_free (term -> tl_api );
936958 vim_free (term -> tl_title );
937959#ifdef FEAT_SESSION
938960 vim_free (term -> tl_command );
@@ -3769,6 +3791,15 @@ handle_drop_command(listitem_T *item)
37693791 vim_free (tofree );
37703792}
37713793
3794+ /*
3795+ * Return TRUE if "func" starts with "pat" and "pat" isn't empty.
3796+ */
3797+ static int
3798+ is_permitted_term_api (char_u * func , char_u * pat )
3799+ {
3800+ return pat != NULL && * pat != NUL && STRNICMP (func , pat , STRLEN (pat )) == 0 ;
3801+ }
3802+
37723803/*
37733804 * Handles a function call from the job running in a terminal.
37743805 * "item" is the function name, "item->li_next" has the arguments.
@@ -3788,9 +3819,9 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
37883819 }
37893820 func = tv_get_string (& item -> li_tv );
37903821
3791- if (STRNCMP (func , "Tapi_" , 5 ) != 0 )
3822+ if (! is_permitted_term_api (func , term -> tl_api ) )
37923823 {
3793- ch_log (channel , "Invalid function name : %s" , func );
3824+ ch_log (channel , "Unpermitted function: %s" , func );
37943825 return ;
37953826 }
37963827
@@ -5545,6 +5576,27 @@ f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED)
55455576}
55465577#endif
55475578
5579+ /*
5580+ * "term_setapi(buf, api)" function
5581+ */
5582+ void
5583+ f_term_setapi (typval_T * argvars , typval_T * rettv UNUSED )
5584+ {
5585+ buf_T * buf = term_get_buf (argvars , "term_setapi()" );
5586+ term_T * term ;
5587+ char_u * api ;
5588+
5589+ if (buf == NULL )
5590+ return ;
5591+ term = buf -> b_term ;
5592+ vim_free (term -> tl_api );
5593+ api = tv_get_string_chk (& argvars [1 ]);
5594+ if (api != NULL )
5595+ term -> tl_api = vim_strsave (api );
5596+ else
5597+ term -> tl_api = NULL ;
5598+ }
5599+
55485600/*
55495601 * "term_setrestore(buf, command)" function
55505602 */
@@ -5608,7 +5660,7 @@ f_term_start(typval_T *argvars, typval_T *rettv)
56085660 + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
56095661 + JO2_CWD + JO2_ENV + JO2_EOF_CHARS
56105662 + JO2_NORESTORE + JO2_TERM_KILL
5611- + JO2_ANSI_COLORS + JO2_TTY_TYPE ) == FAIL )
5663+ + JO2_ANSI_COLORS + JO2_TTY_TYPE + JO2_TERM_API ) == FAIL )
56125664 return ;
56135665
56145666 buf = term_start (& argvars [0 ], NULL , & opt , 0 );
0 commit comments