zsh-users
 help / color / mirror / code / Atom feed
* How completions work, do they require fpath?
@ 2016-01-26 17:18 Sebastian Gniazdowski
  2016-01-26 19:51 ` Sebastian Gniazdowski
  0 siblings, 1 reply; 11+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-26 17:18 UTC (permalink / raw)
  To: Zsh Users

Hello,
my current understanding of the completions is that if a file-function
with name starting with "_", and having "#compdef ..." in first line
of content, is found in $fpath, then, if compinit is run, the function
will be autoloaded and used by _main_complete. Am I missing something
here?

Does this mean that compinit should be best run once after all needed
fpath updates?

A trick to avoid fpath for regular autoload functions has emerged on
this list. Is similar trick possible for a completion? How to load one
without running compinit and most of all, without updating fpath? That
is needed for Zplugin, which is now in nice state (except maybe for
lengthy code and zparseopts issues), e.g. can unload modules (deleting
bindkeys, restoring options, removing aliases, etc.), but doesn't
support adding completions via plugins.

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-26 17:18 How completions work, do they require fpath? Sebastian Gniazdowski
@ 2016-01-26 19:51 ` Sebastian Gniazdowski
  2016-01-27  7:20   ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-26 19:51 UTC (permalink / raw)
  To: Zsh Users

I've found following line in compaudit command:

  if [[ $#_i_files -lt 20 || $_compdir = */Base || -d $_compdir/Base ]]; then

So this suggests that if there is Base sub directory in $_compdir, it
will be used by completion. Tested this and that's true. Quite
contradict to manual which says:

"For  incomplete  installations,  if compinit does not find enough
files eginning with an underscore (fewer than twenty) in the search
path, it will try to find more by adding the directory _compdir  to
the  search path."

Anyway, it seems that I will be able to add completions as follows: a)
create completions/Base/Core directory following the following lines
from compaudit:

    if [[ -d $_compdir/Base/Core ]]; then
      # Add all the Completion subdirectories (CVS-layout)
      _i_addfiles=(${_compdir}/*/*(/^M))

b) mkdir plugin's directory in Base
c) simlink completion files (starting with "_") into that subdirectory
c) set _compdir and run compinit

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-26 19:51 ` Sebastian Gniazdowski
@ 2016-01-27  7:20   ` Bart Schaefer
  2016-01-27  7:59     ` Sebastian Gniazdowski
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2016-01-27  7:20 UTC (permalink / raw)
  To: Zsh Users

On Jan 26,  8:51pm, Sebastian Gniazdowski wrote:
} Subject: Re: How completions work, do they require fpath?
}
} So this suggests that if there is Base sub directory in $_compdir, it
} will be used by completion. Tested this and that's true. Quite
} contradict to manual which says:

No, it doesn't contradict the manual.  The check for a directory named
"Base" is to distinguish "configure --enable-function-subdirs" from the
default configuration which is to avoid creating subdirectories.  If
the "Base" directory is present it's expected to contain all the
files from Completion/Base/ in the source tree, and although the
explicit check is not done the directories AIX/, BSD/, Cygwin/, etc.
are also expected to be found within $_compdir in that case.

This is NOT an indication that you can co-opt these directories for
plugins, nor is it "safe" to run compinit more than once with a new
value of $_compdir -- I'm fairly sure you will mangle, or misuse, or
both, the ~/.zcompdump file if you do so.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-27  7:20   ` Bart Schaefer
@ 2016-01-27  7:59     ` Sebastian Gniazdowski
  2016-01-28  7:11       ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-27  7:59 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On 27 January 2016 at 08:20, Bart Schaefer <schaefer@brasslantern.com> wrote:
> No, it doesn't contradict the manual.  The check for a directory named
> "Base" is to distinguish "configure --enable-function-subdirs" from the
> default configuration which is to avoid creating subdirectories.  If
> the "Base" directory is present it's expected to contain all the
> files from Completion/Base/ in the source tree, and although the
> explicit check is not done the directories AIX/, BSD/, Cygwin/, etc.
> are also expected to be found within $_compdir in that case.

So using _compdir would be a hack, and also, someone can utilize
_compdir for what's it's intended, and overwriting _compdir would
broke their setup.

> This is NOT an indication that you can co-opt these directories for
> plugins, nor is it "safe" to run compinit more than once with a new
> value of $_compdir -- I'm fairly sure you will mangle, or misuse, or
> both, the ~/.zcompdump file if you do so.

So it seems that fpath is needed. I saw Peter's email (workers/12379)
suggesting that work has been done to make fpath the choice for
providing new completions. I wanted to have fpath "clean", and I guess
I can still have it like this: create ~/.zplugin/completions, add it
to fpath, simlink any plugin's "_*" files there. But this will broke
if a completion uses autoload of some functions from plugin's
directory. A very rare case however, I guess.

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-27  7:59     ` Sebastian Gniazdowski
@ 2016-01-28  7:11       ` Bart Schaefer
  2016-01-28  7:37         ` Sebastian Gniazdowski
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2016-01-28  7:11 UTC (permalink / raw)
  To: Zsh Users

On Jan 26,  6:18pm, Sebastian Gniazdowski wrote:
}
} my current understanding of the completions is that if a file-function
} with name starting with "_", and having "#compdef ..." in first line
} of content, is found in $fpath, then, if compinit is run, the function
} will be autoloaded and used by _main_complete. Am I missing something
} here?

No.

} Does this mean that compinit should be best run once after all needed
} fpath updates?

Ideally yes, but really #compdef is just a way to have the compdef
function invoked automatically for some files.  If the plugin is
already calling autoload + compdef directly, compinit isn't needed.

Note that nothing checks for conflicting #compdef, so if two files
both specify the same key bindings the one found later in fpath
will create the binding, but the one found earlier in fpath will
be autoloaded if the two have the same basename.  (So far it has
never come up for two files with the same name, though I believe
there are some conflicting key bindings.)

} A trick to avoid fpath for regular autoload functions has emerged on
} this list. Is similar trick possible for a completion? How to load one
} without running compinit and most of all, without updating fpath?

There's a chunk of code near the end of compinit that handles the
parsing of the #compdef lines.  That would need to be extracted into
its own function so it could be run repeatedly for new files.

Other than that, the shadow-autoload trick already used in zplugin
should work for completion autoloads, although they would not get
recorded in ~/.zcompdump (and you wouldn't want them to be, in that
circumstance).

On Jan 27,  8:59am, Sebastian Gniazdowski wrote:
} Subject: Re: How completions work, do they require fpath?
}
} On 27 January 2016 at 08:20, Bart Schaefer <schaefer@brasslantern.com> wrote:
} > No, it doesn't contradict the manual.  The check for a directory named
} > "Base" is to distinguish "configure --enable-function-subdirs"

Actually I'm only partly right about that.  The real purpose of those
checks in compaudit are so that for example you can start in the zsh
source tree and run:

    Src/zsh -f
    fpath+=($PWD/Completion)
    autoload -Uz compinit
    _compdir=$PWD/Completion compinit -D

and have everything set up to do compsys testing, without having to
first "make install" etc.

} So using _compdir would be a hack, and also, someone can utilize
} _compdir for what's it's intended, and overwriting _compdir would
} broke their setup.

Correct.

} So it seems that fpath is needed.

Perhaps, but see other responses from Peter and above about compdef.

} I wanted to have fpath "clean", and I guess I can still have it

I've been a little puzzled all along about why you object to having
entries in fpath.

} like this: create ~/.zplugin/completions, add it to fpath, simlink
} any plugin's "_*" files there.

There's another possibility:  use zcompile.  Gather up the names of
all the autoloadable files defined by the plugins, and then run for
example

    zcompile ZPLUGINS $all_the_paths_of_autoloadable_files

This will create a (large) file ZPLUGINS.zwc containing all potential
autoloads.  Then just add that file name (not a directory name in
this special case) to fpath:

    fpath+=($PWD/ZPLUGINS.zwc)

and you're done.  Some checks that you don't clobber the file when
a new shell starts up are advised, because zsh typically mmap's it and
shares it.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-28  7:11       ` Bart Schaefer
@ 2016-01-28  7:37         ` Sebastian Gniazdowski
  2016-01-28  7:39           ` Sebastian Gniazdowski
  2016-01-28 19:29           ` Bart Schaefer
  0 siblings, 2 replies; 11+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-28  7:37 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On 28 January 2016 at 08:11, Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Jan 26,  6:18pm, Sebastian Gniazdowski wrote:
> }
> } my current understanding of the completions is that if a file-function
> } with name starting with "_", and having "#compdef ..." in first line
> } of content, is found in $fpath, then, if compinit is run, the function
> } will be autoloaded and used by _main_complete. Am I missing something
> } here?
>
> No.

One thing emerged – I was expecting that empty say "_cp" will just be
ignored, because of lack of #compdef, however it isn't – it blocks
other "_cp" files from loading.

> } Does this mean that compinit should be best run once after all needed
> } fpath updates?
>
> Ideally yes, but really #compdef is just a way to have the compdef
> function invoked automatically for some files.  If the plugin is
> already calling autoload + compdef directly, compinit isn't needed.

Interesting, have to test this

> Other than that, the shadow-autoload trick already used in zplugin
> should work for completion autoloads, although they would not get
> recorded in ~/.zcompdump (and you wouldn't want them to be, in that
> circumstance).

That worries me, I hope my shadowing doesn't interfere with completion
autoloads. That said, it seems that plugin would have to invoke
"compinit" to trigger such autoloads?

> } I wanted to have fpath "clean", and I guess I can still have it
>
> I've been a little puzzled all along about why you object to having
> entries in fpath.

I wasn't 100% sure myself if my expectations of fpath being "clean"
are reasonable. However now after implementing completion support to
Zplugin I see it was a good thing. Really, really nice thing to just
have "~/.zplugin/completions" instead of 10 entries:

https://asciinema.org/a/dmacq18klhw9rfxfffrhweh6a

> } like this: create ~/.zplugin/completions, add it to fpath, simlink
> } any plugin's "_*" files there.
>
> There's another possibility:  use zcompile.  Gather up the names of
> all the autoloadable files defined by the plugins, and then run for
> example
>
>     zcompile ZPLUGINS $all_the_paths_of_autoloadable_files
>
> This will create a (large) file ZPLUGINS.zwc containing all potential
> autoloads.  Then just add that file name (not a directory name in
> this special case) to fpath:
>
>     fpath+=($PWD/ZPLUGINS.zwc)
>
> and you're done.  Some checks that you don't clobber the file when
> a new shell starts up are advised, because zsh typically mmap's it and
> shares it.

Will think about that, currently I've implemented completion handling
via simlinks, and this gives a nice feature – I can check from which
plugin a completion comes from (as seen in the asciinema video)

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-28  7:37         ` Sebastian Gniazdowski
@ 2016-01-28  7:39           ` Sebastian Gniazdowski
  2016-01-28 23:23             ` Bart Schaefer
  2016-01-28 19:29           ` Bart Schaefer
  1 sibling, 1 reply; 11+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-28  7:39 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On 28 January 2016 at 08:37, Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
> On 28 January 2016 at 08:11, Bart Schaefer <schaefer@brasslantern.com> wrote:
>> Ideally yes, but really #compdef is just a way to have the compdef
>> function invoked automatically for some files.  If the plugin is
>> already calling autoload + compdef directly, compinit isn't needed.
>
> Interesting, have to test this

PS. Without compinit, compdef isn't available?

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-28  7:37         ` Sebastian Gniazdowski
  2016-01-28  7:39           ` Sebastian Gniazdowski
@ 2016-01-28 19:29           ` Bart Schaefer
  1 sibling, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 2016-01-28 19:29 UTC (permalink / raw)
  To: Zsh Users

On Jan 28,  8:37am, Sebastian Gniazdowski wrote:
}
} One thing emerged - I was expecting that empty say "_cp" will just be
} ignored, because of lack of #compdef, however it isn't - it blocks
} other "_cp" files from loading.

That doesn't have anything to do with compinit, that's just the way
autoloading always works.  Compinit marks the names to be autoloaded,
but it doesn't control where they come from when autoloading finally
happens.  This was bashed out in agonizing detail with Ray Andrews
back in September.

The reload-and-run trick could circumvent this, that is, if your
autoload shadow were defined before compinit runs, then all of the
functions it touches would load from the place they were found at
compinit time rather than at execution time.

But it would make compinit a bit slower and use a bit more memory.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-28  7:39           ` Sebastian Gniazdowski
@ 2016-01-28 23:23             ` Bart Schaefer
  2016-01-29  8:02               ` Sebastian Gniazdowski
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2016-01-28 23:23 UTC (permalink / raw)
  To: Zsh Users

On Jan 28,  8:39am, Sebastian Gniazdowski wrote:
}
} PS. Without compinit, compdef isn't available?

The compdef function is defined when compinit runs, yes.

The upshot is that you can either:

1. Put your function in a file whose name begins with "_", add a #compdef
   line, put the file in a directory in $fpath, and finally run "compinit"

2. Name your function file any way that you like, run compinit whenever
   it is convenient, put your file in a directory in $fpath or load it
   some other way e.g. "source", but finally add your function to the
   completion system by calling "compdef".

The intention is that #1 is simple and can be rubber-stamped for every
new completion function, but you always have #2 if #1 doesn't work for
some reason.  Either way "compinit" has to happen to set up the rest of
compsys, so there's no point in defining "compdef" independently.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-28 23:23             ` Bart Schaefer
@ 2016-01-29  8:02               ` Sebastian Gniazdowski
  2016-01-31 19:26                 ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-29  8:02 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On 29 January 2016 at 00:23, Bart Schaefer <schaefer@brasslantern.com> wrote:
> The intention is that #1 is simple and can be rubber-stamped for every
> new completion function, but you always have #2 if #1 doesn't work for
> some reason.  Either way "compinit" has to happen to set up the rest of
> compsys, so there's no point in defining "compdef" independently.

There is a plugin (voronkovich/get-jquery) that calls compdef. The
problem is that this requires compinit being run before loading
plugins. But after loading them, compinit is also to be run, to take
account of possible new completions added by the plugins. I guess I
will shadow compdef and load compinit, and warn user about that in
report, that he will have compinit run twice. Unless there is a way to
provide compdef without whole compinit?

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How completions work, do they require fpath?
  2016-01-29  8:02               ` Sebastian Gniazdowski
@ 2016-01-31 19:26                 ` Bart Schaefer
  0 siblings, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 2016-01-31 19:26 UTC (permalink / raw)
  To: Zsh Users

On Jan 29,  9:02am, Sebastian Gniazdowski wrote:
}
} There is a plugin (voronkovich/get-jquery) that calls compdef. The
} problem is that this requires compinit being run before loading
} plugins.

Well, either that or you have to divide the plugins into before/after
compinit subsets, somehow.

There's probably always going to be a way for an uncooperative author
to muck up a plugin manager, just as you could write a C module that
abuses the zmodload linkage conventions.

} Unless there is a way to provide compdef without whole compinit? 

compdef is going to manipulate global variables used/needed by compinit
and later by the rest of compsys.  It's not really possible to run it
standalone beforehand.

You could try this:  Define your own "compdef" whose only action is
to cache its arguments somewhere.  Load all the plugins, then after
compinit is run, play back the cached compdef arguments with the real
compdef.


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-01-31 19:25 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-26 17:18 How completions work, do they require fpath? Sebastian Gniazdowski
2016-01-26 19:51 ` Sebastian Gniazdowski
2016-01-27  7:20   ` Bart Schaefer
2016-01-27  7:59     ` Sebastian Gniazdowski
2016-01-28  7:11       ` Bart Schaefer
2016-01-28  7:37         ` Sebastian Gniazdowski
2016-01-28  7:39           ` Sebastian Gniazdowski
2016-01-28 23:23             ` Bart Schaefer
2016-01-29  8:02               ` Sebastian Gniazdowski
2016-01-31 19:26                 ` Bart Schaefer
2016-01-28 19:29           ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).