How do I find out which function is used for zsh tab completion - zsh-completion

I want to know which function zsh is using for tab completion of a command.
For many commands (make, ls, cd …) I can apparently guess _<COMMANDNAME>, but I might actually have overriden this setting with compdef _mycd cd.
The reasons why I want to know this are two:
I might want to read some function definitions to use parts of them in functions I'm writing
I want to wrote a completion function which itself calls the completion for other commands (like one does in _nice, with the exception that I might not rely on shift; CURRENT--; _normal)

The current completion rules are stored in $_comps.
So one can display the completion rule for cd with echo $_comps[cd] and display the actual function definition with functions $_comps[cd].

Related

Make & show the same information as a command prompt

In my previous questions here on stack we determined my command should run like this.
(& C:\Gyb\Gyb.exe --email $DestinationGYB --action restore --local-folder $GYBFolder --label-restored $GYBLabel --service-account)
The problem with this is if I run that same command in a command prompt I would see a bunch of status information.
When I run the command as above all I see in VSCode is it ran that line and its waiting. How can I make it show me like the command prompt without opening a new window?
here is GYB
https://github.com/jay0lee/got-your-back
Remove the parentheses () around your command if you want to see the output at the same time. Otherwise, this behavior is expected and is not unique to the VSCode terminal.
The group-expression operator () is used to control the order of which code is executed in PowerShell. Expressions are evaluated like order of operations (re: PEMDAS) in Mathematics, the inner-most parentheses get evaluated first. You can also use the group-expression operator to invoke a property or method from the returned expression in the group.
The problem is, group-expressions don't output to the parent level directly, that only happens when the group-expression is done executing. So when you have something that can run for several minutes or even hours like gyb.exe, you don't see that output until the command exits and execution continues.
Contrast this to running outside of the group-expression; as STDOUT is written to the success stream the success stream is immediately written to console as it comes. There is no additional mechanism you are proxying your output through.
Note: You will experience nearly the same behavior with the sub-expression operator $() as well, although do not conflate sub-expressions and group-expressions as they serve different purposes. Here is a link to the official explanation of theGrouping Operator ( ), the Subexpression Operator `$( ) is explained immediately below it.

What fish function controls completion of filenames, and how can I change it?

I am trying to alter the standard logic used by fish to find filename completions. In particular, I want fish not to consider any filename that ends in a tilde (~) character, as these are emacs backup files and are not interesting.
I had assumed that the list of possible completions would be provided by a fish function, which I could then edit to remove the ones ending in tildes. But I cannot find the function. I have looked in the documentation at fishshell.com, and I have also tried functions | grep complete. What function should I be editing?
Unlike most completions file name completions is not implemented as a function; it's baked into the C++ code. See the completer_t::complete_param_expand() method in src/complete.cpp. If you can make a cogent argument for how this type of customization would be implemented I'd encourage you to open an issue.
P.S., Note that functions will not show private functions unless you invoke it as functions -a. I mention this because many completion functions are marked private by beginning their name with an underscore.

Make fish functions private

I defined several helper functions that I only use in one specific fish script. I put them inside the wrapper function but you can still find them via autocompletion.
How can I hide them from auto completion and limit their scope to private?
function outer
function inner_func
echo "I still find this function via automplete"
end
end
Fish does not have private functions, but it is possible this feature will be available in future versions. In the meantime, try using the following technique, a naming convention, or both.
functions -e function_name
Very close to what you need. You can use functions -e function_name before the end of the block to erase it from the global scope.
function outer
function inner_func
echo "I still find this function via automplete."
echo "Not anymore!!"
functions -e inner_func
end
# Let's test this!
inner_func
end
$ outer
I still find this function via automplete.
Not anymore!!
$ inner_func
fish: Unknown command 'inner_func'
Naming Convention
_my_module_func_name
This does not erase the function from the global scope, but it is a general good practice to avoid overriding existing functions unintentionally.
Notes
Functions declared inside a main function file (or functions inside other functions like inner_func) will be available only after its parent function is invoked at least once (this is fish lazy function autoloading), and exist only for the duration of that particular shell session.

auto completion in zsh on 3rd parameter

I have a shell script it's usage is:
foo.sh <name> <type> <*.tar.gz>
I want to setup a complete on 3rd parameter only.
If I press on 1st parameter, just show the usage.
Could I use zsh's zshcomp to do this job?
for example:
foo.sh <tab> # display usage
foo.sh a b <tab> # show files match with *.tar.gz
Is there similar script which I could follow?
Things to read.
Here is a blog post discussing the Z-Shell Completion System.
For a slightly more in-depth discussion, read this unix.stackexchange answer.
And, as always, read the man pages!.
Edit: Forgot to add: echo $fpath will show you the function path that zsh uses. On OSX, I have: /usr/local/share/zsh/4.3.17/functions, (location may vary for you), which contains all the ZSH completion functions. Have a look at _ssh, _ls, _tar etc - they're all there, and they all have lots of nifty features you can learn from.
Addressing the question: the direction you should go.
What you're asking is achievable, though. There are several steps.
You need to write a z-shell completion function. It needs to be located on the fpath; the function-path that zsh uses for it's completion system functions. (If it's a small function, putting it into ~/.zshrc will also work, but isn't recommended).
You want completion on the 3rd parameter. To do that, your function would look something like the following:
_arguments "3:<MENU>:<COMPLETION>"
<MENU> is the menu description, which you'll see if you've enabled the menu descriptions. (That's done using zstyle; read the man pages, or the linked pages, for more information).
<COMPLETION> is the things that you can complete with. For example, if you used:
_arguments "3::(Foo Bar)"
when you ran your script and pressed <TAB>, you'd have the option of either Foo or Bar.
[NOTE: There is no <MENU> in that example. If you don't want a menu descriptor, you can omit it as shown].
You want completion on *.tar files. You can call _files to do that:
_files -g \*.tar
Show usage on first parameter: that'd be a completion with no arguments (ie, argument 1). I'm not sure why you'd want completion on only the third option but not the first two (typical usage descriptions), so I don't know how to answer this. If your script is supposed to be used like this: script foo bar FILE.tar, wouldn't you want to complete the foo and bar arguments as well?
Perhaps a better solution would be displaying the usage when the script is run without parameters.
Full script would look something like the following:
#compdef myscript
_arguments "3:tar files:_files -g \*.tar"

how to "copy" existing completions to other commands in zsh

I have a custom script that takes hostnames as parameters. I know that I can easily copy the existing completion of ssh like this:
compdef myscript=ssh
But that only enables completion of the 1st parameter. Is there an easy way to enable the same completion for all parameters?
I'm not aware of an easy method to enable completion for a custom command. Assuming you've got a command foo with a bunch of allowable arguments bar, bas or baz, then the completion is easy: you can either have foo bar, foo bas, or foo baz. If they're not or'd, though, you could have any combination of the three.
It gets somewhat worse when you've got a 'depth' of more than 1 (bar can take arguments car, cas and caz, for example).
In zsh, my general understanding is that completion for commands is detailed in completion functions. These functions are application specific, because the arguments for each application are specific to those applications. As an example, the tmux (a terminal multiplexer, similar to screen, in case you're not familiar) has a completion function that's fairly complex: here's a link.
If you want to write your own completion functions, the documentation is available and accessible. Here are a bunch of links that I'm (slowly) working my way through - they'll definitely tell you how to get completion working, but there's a lot of reading. The Z-Shell is a complex beast.
Z-Shell completion introduction
Z-Shell functions: Writing and loading your own
ZSH Users Guide, Ch. 6: "Completion, old and new"
You're specifically interested in enabling completion for hostname-like arguments, and you've singled out ssh as the idea. The zsh completion function for ssh is defined in Completion/Unix/Command/_ssh, if you've got the ZSH source. If not, here's a link.
Of course, this SO question is rather similar. compdef alone may do what you want, if myscript and ssh parameters are identical enough.