@@ -18,6 +18,11 @@ static char_u *vim_version_dir __ARGS((char_u *vimdir));
1818static char_u * remove_tail __ARGS ((char_u * p , char_u * pend , char_u * name ));
1919static int copy_indent __ARGS ((int size , char_u * src ));
2020
21+ /* All user names (for ~user completion as done by shell). */
22+ #if defined(FEAT_CMDL_COMPL ) || defined(PROTO )
23+ static garray_T ga_users ;
24+ #endif
25+
2126/*
2227 * Count the size (in window cells) of the indent in the current line.
2328 */
@@ -3782,6 +3787,14 @@ free_homedir()
37823787{
37833788 vim_free (homedir );
37843789}
3790+
3791+ # ifdef FEAT_CMDL_COMPL
3792+ void
3793+ free_users ()
3794+ {
3795+ ga_clear_strings (& ga_users );
3796+ }
3797+ # endif
37853798#endif
37863799
37873800/*
@@ -4451,6 +4464,80 @@ get_env_name(xp, idx)
44514464 return name ;
44524465# endif
44534466}
4467+
4468+ /*
4469+ * Find all user names for user completion.
4470+ * Done only once and then cached.
4471+ */
4472+ static void
4473+ init_users () {
4474+ static int lazy_init_done = FALSE;
4475+
4476+ if (lazy_init_done )
4477+ return ;
4478+
4479+ lazy_init_done = TRUE;
4480+ ga_init2 (& ga_users , sizeof (char_u * ), 20 );
4481+
4482+ # if defined(HAVE_GETPWENT ) && defined(HAVE_PWD_H )
4483+ {
4484+ char_u * user ;
4485+ struct passwd * pw ;
4486+
4487+ setpwent ();
4488+ while ((pw = getpwent ()) != NULL )
4489+ /* pw->pw_name shouldn't be NULL but just in case... */
4490+ if (pw -> pw_name != NULL )
4491+ {
4492+ if (ga_grow (& ga_users , 1 ) == FAIL )
4493+ break ;
4494+ user = vim_strsave ((char_u * )pw -> pw_name );
4495+ if (user == NULL )
4496+ break ;
4497+ ((char_u * * )(ga_users .ga_data ))[ga_users .ga_len ++ ] = user ;
4498+ }
4499+ endpwent ();
4500+ }
4501+ # endif
4502+ }
4503+
4504+ /*
4505+ * Function given to ExpandGeneric() to obtain an user names.
4506+ */
4507+ char_u *
4508+ get_users (xp , idx )
4509+ expand_T * xp UNUSED ;
4510+ int idx ;
4511+ {
4512+ init_users ();
4513+ if (idx < ga_users .ga_len )
4514+ return ((char_u * * )ga_users .ga_data )[idx ];
4515+ return NULL ;
4516+ }
4517+
4518+ /*
4519+ * Check whether name matches a user name. Return:
4520+ * 0 if name does not match any user name.
4521+ * 1 if name partially matches the beginning of a user name.
4522+ * 2 is name fully matches a user name.
4523+ */
4524+ int match_user (name )
4525+ char_u * name ;
4526+ {
4527+ int i ;
4528+ int n = (int )STRLEN (name );
4529+ int result = 0 ;
4530+
4531+ init_users ();
4532+ for (i = 0 ; i < ga_users .ga_len ; i ++ )
4533+ {
4534+ if (STRCMP (((char_u * * )ga_users .ga_data )[i ], name ) == 0 )
4535+ return 2 ; /* full match */
4536+ if (STRNCMP (((char_u * * )ga_users .ga_data )[i ], name , n ) == 0 )
4537+ result = 1 ; /* partial match */
4538+ }
4539+ return result ;
4540+ }
44544541#endif
44554542
44564543/*
0 commit comments