| To: vim_dev@googlegroups.com |
| Subject: Patch 7.3.631 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.3.631 |
| Problem: Cannot complete user names. |
| Solution: Add user name completion. (Dominique Pelle) |
| Files: runtime/doc/map.txt, src/auto/configure, src/config.h.in, |
| src/configure.in, src/ex_docmd.c, src/ex_getln.c, |
| src/misc1.c, src/misc2.c, src/proto/misc1.pro, src/vim.h |
| |
| |
| |
| |
| |
| *** 1227,1232 **** |
| --- 1244,1250 ---- |
| -complete=syntax syntax file names |'syntax'| |
| -complete=tag tags |
| -complete=tag_listfiles tags, file names are shown when CTRL-D is hit |
| + -complete=user user names |
| -complete=var user variables |
| -complete=custom,{func} custom completion, defined via {func} |
| -complete=customlist,{func} custom completion, defined via {func} |
| |
| |
| |
| *** 10631,10637 **** |
| fi |
| |
| for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \ |
| ! getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ |
| memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ |
| setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \ |
| sigvec strcasecmp strerror strftime stricmp strncasecmp \ |
| --- 10631,10637 ---- |
| fi |
| |
| for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \ |
| ! getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ |
| memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ |
| setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \ |
| sigvec strcasecmp strerror strftime stricmp strncasecmp \ |
| |
| |
| |
| *** 161,166 **** |
| --- 161,167 ---- |
| #undef HAVE_FSYNC |
| #undef HAVE_GETCWD |
| #undef HAVE_GETPSEUDOTTY |
| + #undef HAVE_GETPWENT |
| #undef HAVE_GETPWNAM |
| #undef HAVE_GETPWUID |
| #undef HAVE_GETRLIMIT |
| |
| |
| |
| *** 2994,3000 **** |
| dnl Check for functions in one big call, to reduce the size of configure. |
| dnl Can only be used for functions that do not require any include. |
| AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \ |
| ! getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ |
| memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ |
| setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \ |
| sigvec strcasecmp strerror strftime stricmp strncasecmp \ |
| --- 2994,3000 ---- |
| dnl Check for functions in one big call, to reduce the size of configure. |
| dnl Can only be used for functions that do not require any include. |
| AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \ |
| ! getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ |
| memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ |
| setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \ |
| sigvec strcasecmp strerror strftime stricmp strncasecmp \ |
| |
| |
| |
| *** 3515,3520 **** |
| --- 3515,3537 ---- |
| #endif |
| } |
| } |
| + #if defined(FEAT_CMDL_COMPL) |
| + /* Check for user names */ |
| + if (*xp->xp_pattern == '~') |
| + { |
| + for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) |
| + ; |
| + /* Complete ~user only if it partially matches a user name. |
| + * A full match ~user<Tab> will be replaced by user's home |
| + * directory i.e. something like ~user<Tab> -> /home/user/ */ |
| + if (*p == NUL && p > xp->xp_pattern + 1 |
| + && match_user(xp->xp_pattern + 1) == 1) |
| + { |
| + xp->xp_context = EXPAND_USER; |
| + ++xp->xp_pattern; |
| + } |
| + } |
| + #endif |
| } |
| |
| /* |
| |
| *** 5396,5401 **** |
| --- 5413,5419 ---- |
| #endif |
| {EXPAND_TAGS, "tag"}, |
| {EXPAND_TAGS_LISTFILES, "tag_listfiles"}, |
| + {EXPAND_USER, "user"}, |
| {EXPAND_USER_VARS, "var"}, |
| {0, NULL} |
| }; |
| |
| |
| |
| *** 4336,4341 **** |
| --- 4336,4342 ---- |
| * EXPAND_EXPRESSION Complete internal or user defined function/variable |
| * names in expressions, eg :while s^I |
| * EXPAND_ENV_VARS Complete environment variable names |
| + * EXPAND_USER Complete user names |
| */ |
| static void |
| set_expand_context(xp) |
| |
| *** 4681,4686 **** |
| --- 4682,4688 ---- |
| {EXPAND_LOCALES, get_locales, TRUE, FALSE}, |
| #endif |
| {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, |
| + {EXPAND_USER, get_users, TRUE, FALSE}, |
| }; |
| int i; |
| |
| |
| |
| |
| *** 18,23 **** |
| --- 18,28 ---- |
| static char_u *remove_tail __ARGS((char_u *p, char_u *pend, char_u *name)); |
| static int copy_indent __ARGS((int size, char_u *src)); |
| |
| + /* All user names (for ~user completion as done by shell). */ |
| + #if defined(FEAT_CMDL_COMPL) || defined(PROTO) |
| + static garray_T ga_users; |
| + #endif |
| + |
| /* |
| * Count the size (in window cells) of the indent in the current line. |
| */ |
| |
| *** 3782,3787 **** |
| --- 3787,3800 ---- |
| { |
| vim_free(homedir); |
| } |
| + |
| + # ifdef FEAT_CMDL_COMPL |
| + void |
| + free_users() |
| + { |
| + ga_clear_strings(&ga_users); |
| + } |
| + # endif |
| #endif |
| |
| /* |
| |
| *** 4451,4456 **** |
| --- 4464,4543 ---- |
| return name; |
| # endif |
| } |
| + |
| + /* |
| + * Find all user names for user completion. |
| + * Done only once and then cached. |
| + */ |
| + static void |
| + init_users() { |
| + static int lazy_init_done = FALSE; |
| + |
| + if (lazy_init_done) |
| + return; |
| + |
| + lazy_init_done = TRUE; |
| + ga_init2(&ga_users, sizeof(char_u *), 20); |
| + |
| + # if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H) |
| + { |
| + char_u* user; |
| + struct passwd* pw; |
| + |
| + setpwent(); |
| + while ((pw = getpwent()) != NULL) |
| + /* pw->pw_name shouldn't be NULL but just in case... */ |
| + if (pw->pw_name != NULL) |
| + { |
| + if (ga_grow(&ga_users, 1) == FAIL) |
| + break; |
| + user = vim_strsave((char_u*)pw->pw_name); |
| + if (user == NULL) |
| + break; |
| + ((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user; |
| + } |
| + endpwent(); |
| + } |
| + # endif |
| + } |
| + |
| + /* |
| + * Function given to ExpandGeneric() to obtain an user names. |
| + */ |
| + char_u* |
| + get_users(xp, idx) |
| + expand_T *xp UNUSED; |
| + int idx; |
| + { |
| + init_users(); |
| + if (idx < ga_users.ga_len) |
| + return ((char_u **)ga_users.ga_data)[idx]; |
| + return NULL; |
| + } |
| + |
| + /* |
| + * Check whether name matches a user name. Return: |
| + * 0 if name does not match any user name. |
| + * 1 if name partially matches the beginning of a user name. |
| + * 2 is name fully matches a user name. |
| + */ |
| + int match_user(name) |
| + char_u* name; |
| + { |
| + int i; |
| + int n = (int)STRLEN(name); |
| + int result = 0; |
| + |
| + init_users(); |
| + for (i = 0; i < ga_users.ga_len; i++) |
| + { |
| + if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0) |
| + return 2; /* full match */ |
| + if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0) |
| + result = 1; /* partial match */ |
| + } |
| + return result; |
| + } |
| #endif |
| |
| /* |
| |
| |
| |
| *** 1110,1115 **** |
| --- 1110,1118 ---- |
| free_all_marks(); |
| alist_clear(&global_alist); |
| free_homedir(); |
| + # if defined(FEAT_CMDL_COMPL) |
| + free_users(); |
| + # endif |
| free_search_patterns(); |
| free_old_sub(); |
| free_last_insert(); |
| |
| |
| |
| *** 50,55 **** |
| --- 50,56 ---- |
| void vim_beep __ARGS((void)); |
| void init_homedir __ARGS((void)); |
| void free_homedir __ARGS((void)); |
| + void free_users __ARGS((void)); |
| char_u *expand_env_save __ARGS((char_u *src)); |
| char_u *expand_env_save_opt __ARGS((char_u *src, int one)); |
| void expand_env __ARGS((char_u *src, char_u *dst, int dstlen)); |
| |
| *** 57,62 **** |
| --- 58,65 ---- |
| char_u *vim_getenv __ARGS((char_u *name, int *mustfree)); |
| void vim_setenv __ARGS((char_u *name, char_u *val)); |
| char_u *get_env_name __ARGS((expand_T *xp, int idx)); |
| + char_u *get_users __ARGS((expand_T *xp, int idx)); |
| + int match_user __ARGS((char_u* name)); |
| void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one)); |
| char_u *home_replace_save __ARGS((buf_T *buf, char_u *src)); |
| int fullpathcmp __ARGS((char_u *s1, char_u *s2, int checkname)); |
| |
| |
| |
| *** 782,787 **** |
| --- 782,788 ---- |
| #define EXPAND_OWNSYNTAX 39 |
| #define EXPAND_LOCALES 40 |
| #define EXPAND_HISTORY 41 |
| + #define EXPAND_USER 42 |
| |
| /* Values for exmode_active (0 is no exmode) */ |
| #define EXMODE_NORMAL 1 |
| |
| |
| |
| *** 716,717 **** |
| --- 716,719 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 631, |
| /**/ |
| |
| -- |
| "Marriage is the process of finding out what kind of man your wife |
| would have preferred" |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ an exciting new programming language -- http://www.Zimbu.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |