@@ -6923,6 +6923,103 @@ ex_wrongmodifier(exarg_T *eap)
69236923 eap -> errmsg = ex_errmsg (e_invalid_command_str , eap -> cmd );
69246924}
69256925
6926+ #ifdef FEAT_EVAL
6927+ /*
6928+ * Evaluate the 'findexpr' expression and return the result. When evaluating
6929+ * the expression, v:fname is set to the ":find" command argument.
6930+ */
6931+ static list_T *
6932+ eval_findexpr (char_u * ptr , int len )
6933+ {
6934+ sctx_T saved_sctx = current_sctx ;
6935+ int use_sandbox = FALSE;
6936+ char_u * findexpr ;
6937+ char_u * arg ;
6938+ typval_T tv ;
6939+ list_T * retlist = NULL ;
6940+
6941+ if (* curbuf -> b_p_fexpr == NUL )
6942+ {
6943+ use_sandbox = was_set_insecurely ((char_u * )"findexpr" , OPT_GLOBAL );
6944+ findexpr = p_fexpr ;
6945+ }
6946+ else
6947+ {
6948+ use_sandbox = was_set_insecurely ((char_u * )"findexpr" , OPT_LOCAL );
6949+ findexpr = curbuf -> b_p_fexpr ;
6950+ }
6951+
6952+ set_vim_var_string (VV_FNAME , ptr , len );
6953+ current_sctx = curbuf -> b_p_script_ctx [BV_FEXPR ];
6954+
6955+ arg = skipwhite (findexpr );
6956+
6957+ if (use_sandbox )
6958+ ++ sandbox ;
6959+ ++ textlock ;
6960+
6961+ // Evaluate the expression. If the expression is "FuncName()" call the
6962+ // function directly.
6963+ if (eval0_simple_funccal (arg , & tv , NULL , & EVALARG_EVALUATE ) == FAIL )
6964+ retlist = NULL ;
6965+ else
6966+ {
6967+ if (tv .v_type == VAR_LIST )
6968+ retlist = list_copy (tv .vval .v_list , TRUE, TRUE, get_copyID ());
6969+ clear_tv (& tv );
6970+ }
6971+ if (use_sandbox )
6972+ -- sandbox ;
6973+ -- textlock ;
6974+ clear_evalarg (& EVALARG_EVALUATE , NULL );
6975+
6976+ set_vim_var_string (VV_FNAME , NULL , 0 );
6977+ current_sctx = saved_sctx ;
6978+
6979+ return retlist ;
6980+ }
6981+
6982+ /*
6983+ * Use 'findexpr' to find file 'findarg'. The 'count' argument is used to find
6984+ * the n'th matching file.
6985+ */
6986+ static char_u *
6987+ findexpr_find_file (char_u * findarg , int findarg_len , int count )
6988+ {
6989+ list_T * fname_list ;
6990+ char_u * ret_fname = NULL ;
6991+ char_u cc ;
6992+ int fname_count ;
6993+
6994+ cc = findarg [findarg_len ];
6995+ findarg [findarg_len ] = NUL ;
6996+
6997+ fname_list = eval_findexpr (findarg , findarg_len );
6998+ fname_count = list_len (fname_list );
6999+
7000+ if (fname_count == 0 )
7001+ semsg (_ (e_cant_find_file_str_in_path ), findarg );
7002+ else
7003+ {
7004+ if (count > fname_count )
7005+ semsg (_ (e_no_more_file_str_found_in_path ), findarg );
7006+ else
7007+ {
7008+ listitem_T * li = list_find (fname_list , count - 1 );
7009+ if (li != NULL && li -> li_tv .v_type == VAR_STRING )
7010+ ret_fname = vim_strsave (li -> li_tv .vval .v_string );
7011+ }
7012+ }
7013+
7014+ if (fname_list != NULL )
7015+ list_free (fname_list );
7016+
7017+ findarg [findarg_len ] = cc ;
7018+
7019+ return ret_fname ;
7020+ }
7021+ #endif
7022+
69267023/*
69277024 * :sview [+command] file split window with new file, read-only
69287025 * :split [[+command] file] split window with current or new file
@@ -6972,11 +7069,22 @@ ex_splitview(exarg_T *eap)
69727069 {
69737070 char_u * file_to_find = NULL ;
69747071 char * search_ctx = NULL ;
6975- fname = find_file_in_path (eap -> arg , (int )STRLEN (eap -> arg ),
6976- FNAME_MESS , TRUE, curbuf -> b_ffname ,
6977- & file_to_find , & search_ctx );
6978- vim_free (file_to_find );
6979- vim_findfile_cleanup (search_ctx );
7072+
7073+ if (* get_findexpr () != NUL )
7074+ {
7075+ #ifdef FEAT_EVAL
7076+ fname = findexpr_find_file (eap -> arg , (int )STRLEN (eap -> arg ),
7077+ eap -> addr_count > 0 ? eap -> line2 : 1 );
7078+ #endif
7079+ }
7080+ else
7081+ {
7082+ fname = find_file_in_path (eap -> arg , (int )STRLEN (eap -> arg ),
7083+ FNAME_MESS , TRUE, curbuf -> b_ffname ,
7084+ & file_to_find , & search_ctx );
7085+ vim_free (file_to_find );
7086+ vim_findfile_cleanup (search_ctx );
7087+ }
69807088 if (fname == NULL )
69817089 goto theend ;
69827090 eap -> arg = fname ;
@@ -7241,27 +7349,37 @@ ex_find(exarg_T *eap)
72417349 if (!check_can_set_curbuf_forceit (eap -> forceit ))
72427350 return ;
72437351
7244- char_u * fname ;
7352+ char_u * fname = NULL ;
72457353 int count ;
72467354 char_u * file_to_find = NULL ;
72477355 char * search_ctx = NULL ;
72487356
7249- fname = find_file_in_path (eap -> arg , (int )STRLEN (eap -> arg ), FNAME_MESS ,
7250- TRUE, curbuf -> b_ffname , & file_to_find , & search_ctx );
7251- if (eap -> addr_count > 0 )
7357+ if (* get_findexpr () != NUL )
7358+ {
7359+ #ifdef FEAT_EVAL
7360+ fname = findexpr_find_file (eap -> arg , (int )STRLEN (eap -> arg ),
7361+ eap -> addr_count > 0 ? eap -> line2 : 1 );
7362+ #endif
7363+ }
7364+ else
72527365 {
7253- // Repeat finding the file "count" times. This matters when it appears
7254- // several times in the path.
7255- count = eap -> line2 ;
7256- while (fname != NULL && -- count > 0 )
7366+ fname = find_file_in_path (eap -> arg , (int )STRLEN (eap -> arg ), FNAME_MESS ,
7367+ TRUE, curbuf -> b_ffname , & file_to_find , & search_ctx );
7368+ if (eap -> addr_count > 0 )
72577369 {
7258- vim_free (fname );
7259- fname = find_file_in_path (NULL , 0 , FNAME_MESS ,
7260- FALSE, curbuf -> b_ffname , & file_to_find , & search_ctx );
7370+ // Repeat finding the file "count" times. This matters when it appears
7371+ // several times in the path.
7372+ count = eap -> line2 ;
7373+ while (fname != NULL && -- count > 0 )
7374+ {
7375+ vim_free (fname );
7376+ fname = find_file_in_path (NULL , 0 , FNAME_MESS ,
7377+ FALSE, curbuf -> b_ffname , & file_to_find , & search_ctx );
7378+ }
72617379 }
7380+ VIM_CLEAR (file_to_find );
7381+ vim_findfile_cleanup (search_ctx );
72627382 }
7263- VIM_CLEAR (file_to_find );
7264- vim_findfile_cleanup (search_ctx );
72657383
72667384 if (fname == NULL )
72677385 return ;
0 commit comments