Is there any standard way of providing list of program switches, so it would be possible for zsh to determine possible completions? Or must it provided directly to zsh developers and only they can add completions to zsh?
Your first stop should be man zshcompsys.
Then you could look at an example such as /usr/share/zsh/functions/Completion/Unix/_vim.
The Z-Shell doesn't automatically know what possible switches work with which binary files. As far as I'm aware, there's no standard way for a shell to determine this.
ZSH works by using completion functions, which are written for specific programs. For example, zsh ships with completion functions for ssh, cvs, git, ls, etc.
If you want to look at these completion functions, you can. If you're in a zsh shell, echo $fpath to see the function path that zsh uses to load completion functions. There's a directory called /usr/local/share/zsh/4.3.17/function (location may vary for distributions / zsh versions), which has a bunch of files beginning with _ - _ssh, _cvs, etc. Those are the completion functions.
One massive clue that these are not generated automatically comes from a comment in the _ssh completion function that ships with 4.3.17 (may or may not be in your specific version):
# Completions currently based on OpenSSH 5.9 (released on 2011-09-06).
#
# TODO: update ssh-keygen (not based on 5.9)
# TODO: sshd, ssh-keyscan, ssh-keysign
Providing completion for the Z-Shell: using fpath
You can write your own completion functions, and developers can write functions for their programs and submit to the zsh developers for inclusion. Z-Shell completion functions go somewhere on the fpath.
If the program, say foobar, follows GNU conventions for options, you can use:
compdef _gnu_generic foobar
Otherwise you can write your own functions. The easiest to use IMO is _describe.
Create a file _foobar with contents:
#compdef foobar
cmds=(
'--one:option one'
'--four:option four'
'no-slashes:options do not need to start with a slash'
)
_describe 'foobar' cmds
Place the file somewhere in your $fpath
Add compdef _foobar foobar
If You are using ruby with the optparse package there is a hidden flag --*-completion-zsh=NAME that will output all that is needed for the completion for that ruby program. Store it in a file named _NAME somewhere in your $fpath and it will work. NAME should be exactly what your program/script is called.
I use a folder in my $HOME for that and added the path to $fpath but that required an additional line in my .zshrc:
autoload -U ~/.completion/*(:t)
Related
Is there a way to make zsh complete parameters of commands (just like the fish shell do). For example, when I type ls -- and use TAB it will pop up a list of all ls parameters.
I know that I can use fish shell for this, and I know that fish shell is amazing, but there is a lot of missing functionalities in the fish shell. That's why I am looking to bring this parameter completion in zsh.
Try with single hyphen, like ls -. All built in commands are working fine. Btw for custom oh-my-zsh plugin autocompletion, it depends on plugin configuration.
oh-my-zsh has over 200 plugins for different commands. But unfortunately the auto completions are all hand made. So there will be never auto complete function for every command.
I wasn't able to find a documentation for the widely used autoload command in zsh. Does anybody can explain it in plain English?
A bit more specific: What does autoloading of modules mean, for example in this line:
autoload -Uz vcs_info
What does it do?
I've tried autoload --help, man autoload, googling - no success. Thanks!
The autoload feature is not available in bash, but it is in ksh (korn shell) and zsh. On zsh see man zshbuiltins.
Functions are called in the same way as any other command. There can be a name conflict between a program and a function. What autoload does is to mark that name as being a function rather than an external program. The function has to be in a file on its own, with the filename the same as the function name.
autoload -Uz vcs_info
The -U means mark the function vcs_info for autoloading and suppress alias expansion. The -z means use zsh (rather than ksh) style. See also the functions command.
Edit (from comment, as suggested by #ijoseph):
So it records the fact that the name is a function and not an external program - it does not call it unless the -X option is used, it just affects the search path when it is called. If the function name does not collide with the name of a program then it is not required. Prefix your functions with something like f_ and you will probably never need it.
For more detail see http://zsh.sourceforge.net/Doc/Release/Functions.html.
autoload tells zsh to look for a file in $FPATH/$fpath containing a function definition, instead of a file in $PATH/$path containing an executable script or binary.
Script
A script is just a sequence of commands that get executed when the script is run. For example, suppose you have a file called hello like this:
echo "Setting 'greeting'"
greeting='Hello'
If the file is executable and located in one of the directories in your $PATH, then you can run it as a script by just typing its name. But scripts get their own copy of the shell process, so anything they do can't affect the calling shell environment. The assignment to greeting above will be in effect only within the script; once the script exits, it won't have had any impact on your interactive shell session:
$ hello
Setting 'greeting'
$ echo $greeting
$
Function
A function is instead defined once and stays in the shell's memory; when you call it, it executes inside the current shell, and can therefore have side effects:
hello() {
echo "Setting 'greeting'"
greeting='Hello'
}
$ hello
Setting 'greeting'
$ echo $greeting
Hello
So you use functions when you want to modify your shell environment. The Zsh Line Editor (ZLE) also uses functions - when you bind a key to some action, that action is defined as a shell function (which has to be added to ZLE with the zle -N command).
Now, if you have a lot of functions, then you might not want to define all of them in your .zshrc every time you start a new shell; that slows down shell startup and uses memory to store functions that you might not wind up calling during the lifetime of that shell. So you can instead put the function definitions into their own files, named after the functions they define, and put the files into directories in your $FPATH, which works like $PATH.
Zsh comes with a bunch of standard functions in the default $FPATH already. But it won't know to look for a command there unless you've first told it that the command is a function.
That's what autoload does: it says "Hey, Zsh, this command name here is a function, so when I try to run it, go look for its definition in my FPATH, instead of looking for an executable in my PATH."
The first time you run command which Zsh determines is autoloaded function, the shell sources the definition file. Then, if there's nothing in the file except the function definition, or if the shell option KSH_AUTOLOAD is set, it proceeds to call the function with the arguments you supplied. But if that option is not set and the file contains any code outside the function definition (like initialization of variables used by the function), the function is not called automatically. In that case it's up to you to call the function inside the file after defining it so that first invocation will work.
When I use the command typeset -f in ksh, a list of functions with their definition is displayed in stdout.
I tried to search where those functions are defined, but I couldn't find any hint about them. Can anyone help me finding them?
EDIT
I'm just learning the use of the typeset command, typing man typeset game me nothing (no manual entry for typeset).
In order to define functions that will be displayed using typeset -f, we need to define a function and export it using typeset -xf.
Functions can be declared in the .profile, or files called from .profile or put in a dir that is referenced by the FPATH variable (and proabably other places too). Read your man ksh carefully for the order of files that are processed on startup. Search for the 'Invocation', 'Files', and 'Functions' sections.
Also, there are a group of default functions that ksh sets up. So please edit your question to show the function names that your concerned with.
IHTH
Shells don't keep a record of where functions (or aliases, or variables, etc...) are defined. Conceptually, and notwithstanding interactive usage features like shell history, shells read commands from input one at a time, execute them, and then forget them. Sometimes those commands come from interactive input, sometimes they come from scripts. Sometimes they have side effects like defining a function in the shell's environment, but the shell still doesn't remember the command or its position in the shell's input stream after it's finished executing it.
Is there any way to find out the variables available in the scope of the shell script.
the scenario is like this, we are using some third party tools and we can customize the output with creating shell scripts with a particular naming convention. we know that certain parameters are being passed to our custom shell scripts but we want to know what else is being passed.
thanks.
The command is set
From the bash manual page
set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
Without options, the name and value of each shell variable are displayed in a
format that can be reused as input.
Do not confuse this with env which will print out the values of environment variables not shell variables. shell variables can be marked for automatic export into the environment of subsequent child processes using the export command.
scope as a programming term, only really applies to shell variables - commands like typeset and local can be used in some shells (ksh and bash) to allow the use of scoped shell variables within functions. environment variables are global to a instance of a processes.
It's very easy ;)
env
It sounds like you want environment variables, so use export -p. The output (which consists of lines of the form export variable=value per POSIX) is quoted in such a way that it can be parsed by the shell. It's also sorted by variable name in most shells.
If you want all shell parameters (for your use case, this would be relevant only if the scripts were sourced rather than called as separate programs), use set (again, it's in POSIX, the output is properly quoted for reparsing, and it's sorted in most shells).
This may be really simplistic but...
grep = <your script>
How to create a new environment variable in unix and use it in a program??????
You can tell what shell you're running by ps -o comm= -p $$ — I think that's more-or-less universal. So, in bash and certain similar shells...
If you want to create the variable for one specific run, you can do
MYVAR=value the_command_that_needs_myvar
If you want to create it for an entire shell session (ie. until you log out):
export MYVAR=value
...and then you can run:
the_command_that_needs_myvar
...as many times as you like during that session, and it will still see MYVAR as having the value value.
If you want it to be set for yourself, for all your login sessions, put it in ~/.profile.
Please note that bash's initialisation files can be one great big WTF. Depending on whether it is run interactively, over a network, locally, AND depending on whether it is invoked as sh or bash, it will selectively read some combination of ~/.bashrc, ~/.profile and ~/.bash_profile. Read the FILES section of the bash man page for details.
If you want it to be set for every user, every time they log in, put it in the file /etc/profile (although there's also /etc/environment, I'm not sure how widely used that is.).
Check out the question "How to set environment variable for everyone under my linux system?" for some more details, too.
(Beware, some of this advice will vary depending on if you, or other users, use bash, dash, csh, ksh, etc... but it should work for most use cases.)
Depends on the shell. In bash, you can use:
export myvar=xyz
which will set the variable and make it available to other programs.
If you want to set it for one invocation of a program, you can use:
myvar=xyz ./myprog
This will have it set for the myprog process but not after it exits.
See setenv(3) and getenv(3) functions.