From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23339 invoked by alias); 29 Jan 2014 16:29:46 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 18378 Received: (qmail 17205 invoked from network); 29 Jan 2014 16:29:31 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 From: Greg Klanderman To: zsh-users@zsh.org Subject: Re: [Feature suggestion] (user configurable) timeout for generating completion lists Reply-to: gak@klanderman.net Date: Wed, 29 Jan 2014 11:29:24 -0500 In-reply-to: <140125124934.ZM23767@torch.brasslantern.com> (Bart Schaefer's message of "Sat, 25 Jan 2014 12:49:34 -0800") Message-id: <87eh3q3g63.fsf@lwm.klanderman.net> User-Agent: Gnus/5.1008 (Gnus v5.10.8) XEmacs/21.4.22 (linux) References: <140122000435.ZM1516@torch.brasslantern.com> <140123171659.ZM19422@torch.brasslantern.com> <87iot91lp8.fsf@lwm.klanderman.net> <140125124934.ZM23767@torch.brasslantern.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii >>>>> On January 25, 2014 Bart Schaefer wrote: > On Jan 24, 9:46am, Greg Klanderman wrote: > } > } For slow completion due to calling out to a separate process for > } completions (_git comes to mind) if that is not currently > } interruptible it seems like there might be some hope of adding a > } timeout or ensuring C-c will interrupt. > This is the thing I had a hard time reproducing. Even if I force > the completion function to be very busy with a loop, I can interrupt > it. (Oddly the value of $? is always 0 in _main_complete after I > hit ^C, so I can't detect the signal and issue a message.) Did you try a busy completion function, or external process? Great if this case works well.. I didn't test it and haven't noticed a problem, but I don't think I commonly use any completion that calls out to an external program and is slow. I know some have complained about the git completion with big repos, but I'm fairly new to git and haven't found a case that's slow yet. If someone has an example, let me know.. > } The biggest problem I've had with completion being unresponsive was > } due to automounts at work (currently have ~53k under a handful of > } mount points). Using the fake-files zstyle mostly works until > } completion tries to stat all those automounts > I think this is analogous to the situation that started this thread. Similar issue, though my case will only come up if you go to the trouble of setting up a fake-files zstyle with the automount points. The slowness is from stat'ing 53k automounts, and it does not seem to be interruptible with C-c. Also if you hit tab after "/home/" it ends up actually mounting as many of the automounts under /home as it can before you manage to kill the shell from another window, which is non-ideal. In the original post it seemed that the slow call was probably reading a large directory on a slow NFS mount. > } to determine the file type in order to append a '/' or ' '. > ... which is difficult to do if there's an external program doing the > stat. Not impossible, but it means passing a lot of structured data > through a pipe, which might slow down more common cases. The protobuf library works well for that sort of thing though I'm not sure if it has straight C bindings. > (Maybe this is why Meino wants "find -print0 -ls". :-> ) > } So locally I run zsh with a > } small patch (to ztat()) that uses a shell variable to configure > } automount roots under which all immediate entries are assumed to be > } directories without stat'ing. Works great, though I don't think > } several years ago you were willing to incorporate that into zsh. > Doesn't sound terrible, I'll attach the patch below, if you'd be willing to incorporate something like it let me know, I'd certainly prefer to have it part of zsh. I would add documentation of course. It gets used like this: completion_nostat_dirs=(/home /net) zstyle ':completion:*' fake-files '/home:foo bar baz' '/net:aaa bbb ccc' ... > but I don't think it would solve the original > problem, which if I'm right is that NFS listing is big/slow after the > mount is already completed. Correct. Greg Index: Src/init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.122 diff -u -r1.122 init.c --- Src/init.c 5 Jan 2012 20:01:25 -0000 1.122 +++ Src/init.c 9 Jan 2012 20:09:36 -0000 @@ -827,6 +827,8 @@ modulestab = newmoduletable(17, "modules"); linkedmodules = znewlinklist(); + completion_nostat_dirs = mkarray(NULL); + /* Set default prompts */ if(unset(INTERACTIVE)) { prompt = ztrdup(""); Index: Src/params.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/params.c,v retrieving revision 1.177 diff -u -r1.177 params.c --- Src/params.c 7 Jan 2012 23:21:00 -0000 1.177 +++ Src/params.c 9 Jan 2012 20:09:36 -0000 @@ -104,6 +104,10 @@ zoptind, /* $OPTIND */ shlvl; /* $SHLVL */ +/**/ +mod_export +char **completion_nostat_dirs; + /* $histchars */ /**/ @@ -356,6 +360,8 @@ IPDEF9F("*", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), +IPDEF9("completion_nostat_dirs", &completion_nostat_dirs, NULL), + /* * This empty row indicates the end of parameters available in * all emulations. Index: Src/Zle/compresult.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/compresult.c,v retrieving revision 1.82 diff -u -r1.82 compresult.c --- Src/Zle/compresult.c 14 May 2011 00:07:42 -0000 1.82 +++ Src/Zle/compresult.c 9 Jan 2012 20:09:37 -0000 @@ -868,11 +868,25 @@ ztat(char *nam, struct stat *buf, int ls) { int ret; + char **pp; nam = unmeta(nam); if (!nam) return -1; + for (pp = completion_nostat_dirs; *pp; pp++) { + int len = strlen(*pp); + + if ((*pp)[len-1] == '/') + len--; + + if (strncmp(nam, *pp, len) == 0 && nam[len] == '/' && strchr(nam+len+1, '/') == NULL) { + memset(buf, 0, sizeof(*buf)); + buf->st_mode = S_IFDIR; /* pretend it's a directory */ + return 0; + } + } + if ((ret = ls ? lstat(nam, buf) : stat(nam, buf))) { char *p, *q;