Does bash source bash completion files in /usr/local/etc/bash_completion.d by default? - bash

I have a bunch of bash completion files in
/usr/local/etc/bash_completion.d
most of the scripts in there have something like this at the bottom of them:
complete -F _tmux tmux
the above is for tmux.
My question is - it doesn't look like bash by default sources these files?
I see some instructions online about doing something like this:
for f in '/usr/local/etc/bash_completion.d/'*; do
source "$f"
done;
do I need to do this manually or should bash be doing this out of the box?

This varies depending on your platform and/or versions of bash and bash-completion. For example:
Ubuntu
On Ubuntu 20.04 the file /etc/bash_completion does this:
. /usr/share/bash-completion/bash_completion
And in that file I find
for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share}; do
dirs+=( $dir/bash-completion/completions )
done
Which indicates that /usr/local/share/bash-completion/completions is scanned for completion scripts. Empirical experiments supports this.
MacOS/Brew
I could not find anything about bash completion in /etc or /usr/share on my MacOS 11.2.3. Which indicates that bare Darwin does not have bash completion, which makes sense since Apple have left Bash at 3.2 because of licensing. Might have for zsh, though, I didn't look.
/usr/local/etc/bash-completion.d, which you reference, is a part of the Homebrew installation under /usr/local. In there I found some completion scripts, but not the activation script. You should not have to activate those explicitly yourself.
I did find /usr/local/share/bash-completion, again from Homebrew, and it has the script bash_completion. In it are the same lines as Ubuntu, which also makes sense since Homebrew is kinda complete "GNU" but under /usr/local. But it also reference the directory /usr/local/etc/bash-completion.d. Sourcing /usr/local/share/bash-completion/bash_completion added the completion from that directory also.
But /usr/local/share/bash-completion/bash_completion is not executed by default, so you have to add that to your ~/bash_profile or ~/profile as described here. It also describes how to handle zsh and fish.
Cygwin
Cygwin is another Posix-compliant environment which has bash completion. (I haven't checked if bash completion is part of the Posix standard, though) After installing the bash-completion package there is /usr/share/bash-completion/bash_completion as Ubuntu and Homebrew has. Here there is no /etc/bash_completion and as the ~/.bashrc I had (generated long ago) did only look for this completions wasn't activated.
Summary
Many GNU-like environments support bash_completion but you might have to
install a package
ensure that it is sourced when you log in, which is not always the case by default
If it is not activated by default in your environment, you can activate it by sourcing the "root" script (in /etc, /usr/share/bash-completion or where it might be located) from your .bashrc, bash_profile or similar.
I'm guessing YMMV for all other possible platforms (other Linux distros, MSYS2 etc.) but the above might help you to figure out how to enable completion. Which is really helpful when available.

Related

How to provide shell completion with python a package? [duplicate]

I am writing a command line tool in python and using pip to distribute it. I have written some scripts (one for bash and one for zsh) to allow the tool to have tab completion. Is there a way to get pip to install these scripts when someone does a pip install?
For example:
I have a completion.bash file. When someone does
pip install mypackage
It will also source the bash file.
I'm pretty sure I can do this for linux and bash by putting the script in my data_files section in the setup.py script.
data_file=[
('/etc/bash_completion.d', ['bin/completion.bash'])
],
But how can I do this so it is platform and shell independent? I need it to work for mac/linux in both bash and zsh. If possible, even support windows.
Is this possible? And if so, how?
In case it matters, here is my bash script:
_foo_complete() {
COMPREPLY=()
local words=( "${COMP_WORDS[#]}" )
local word="${COMP_WORDS[COMP_CWORD]}"
words=("${words[#]:1}")
local completions="$(foo completer --cmplt=\""${words[*]}"\")"
COMPREPLY=( $(compgen -W "$completions" -- "$word") )
}
complete -F _foo_complete foo
I am currently installing it by just running source completion.bash
You are asking several different questions.
First, there's no cross-platform or cross-shell solution for defining custom shell-completions. The one you posted works for bash, but in tcsh, for example, you use tcsh's complete command, which works differently than bash's.
Second, sourcing the files which contain those completion-definitions at the time of pip install wouldn't do much good. The completions might work in that very session, but what you probably want is for them to take effect in future sessions (i.e. shell invocations) as well. For that, your files would have to be sourced each time the shell starts (e.g. from within user's .bashrc, in case of bash).
This measn that "installing" your files simply means placing them somewhere, and suggesting the users should source them from their respective dot-rc file. Even if you could, you shouldn't try to "force" it. Give your users the option to add that to their dot-rc file if they want.
The best approach would probably be to include in your package a completion-definitions file per supported shell, e.g. complete.bash, complete.tcsh, and god knows what for windows (sorry, I'm not a windows user).

Can zsh complete command flags?

Is there some way to get zsh to complete long flag names on the command line?
$ command --reall<tab>
$ command --really-long-flag-name
Seems like a zshy thing to do.
The short answer is yes, or course it can.
To turn on zsh’s completion system, you need to do the following – probably in a startup file like your ~/.zshrc:
autoload -U compinit && compinit
On most modern Unix-like systems, once you do that you ought to find that many commands already have their flags and parameters completed, because zsh ships with a library of completion functions for common Unix commands and utilities. This library ought to be installed in a location like /usr/local/share/zsh/function (or similar, depending on your system) and consists of a bunch of scripts with filenames starting in a _ character, each of which defines the completion for a specific command.
If a command or utility you’re interested in is not yet completed correctly by zsh, you have several options:
Look into the zsh-completions package. (It may well be installable by your operating system or distribution’s package manager.)
Read the documentation for the tool you wish to have completion. Many Unix utilities ship with completion scripts for bash and/or zsh, or with some way of generating completion scripts.
If all else fails, read the documentation on zsh’s completion system (or find a good book or online tutorial) and write it yourself. This can — obviously — be non-trivial!
Reading that zsh documentation might also show you how to do other things that you may not even know yet that you want, like turning on menu-based completion.

Remote path completion with scp on OSX

On Linux, you can do
$ scp some-file.txt user#remote.host.com:/some/pa<tab>
and it would autocomplete the remote path, if you have key based authentication up and running for that host. However, on OSX it doesn't seem to work, using iTerm2. Any hints?
This depends on your shell. In case you are using bash you need the correct bash completion scripts.
See the Bash completion project, and especially this script: https://github.com/scop/bash-completion/blob/master/completions/ssh
Default location where those have to be put is /etc/bash_completion and then you can load them from your .bashrcor .profile file by adding something like . /etc/bash_completion (mind the . to source the file)
While focused on Linux they should work on Mac, too.
Homebrew and other software managers provide bash-completion, too. If installed check your .bashrc/.profile according to the instructions to properly load it.

Too many bash initialization files?

I just installed GMT4 (Generic Mapping Tools) from MacPorts and have run into some serious issues with terminal...
When using the ls command in terminal I get the following:
-bash: ls: command not found
To fix this I've tried many things that I read many different places online. I've changed the following files to include /usr and /bin:
~/.bashrc
~/.bash_profile
~/.profile
Doing so gave me back the sudo command which I had previously lost.
However, I still am not able to use ls in a new terminal window without manually exporting the path("new session"). This has been causing problems when I'm running shell scripts that use system functions. So I'm starting to wonder what exactly those three files do and if maybe having three files doing the same thing is causing them to interfere with one another. If anyone can tell me where I need to add these PATHS that would be great; I dunno, maybe I can delete one of these files or something ELSE is conflicting. Right now I just run " export PATH=$PATH:/usr" in each new terminal window and it works for that session.
I'm running Mac OS X 10.6 on a early 2011 MacBook Pro with 4GB of RAM.
Background for those who are interested:
My end goal is to use Relax to model viscoelastic relaxation in a mid-oceanic ridge system to come up with some sort of constitutive law or power-relation between slip magnitude and the location of greatest tensional stress in the lithosphere due to normal faulting.
The Bash manual actually explains these files fairly thoroughly. However, the manual does not describe how these mechanisms are usually used in practice. What follows is a brief, abridged version of what is common best practice.
.profile is read at login by both sh and bash.
.bashrc is read by non-login Bash shells. By convention, .bash_profile sources .bashrc in turn.
.bash_profile is read at login by Bash. If this file exists, .profile is not read. By convention, .bash_profile should source .profile if it exists.

How can I make bash deal with long param using "getopt" command in mac?

I want to make my bash script deal with long parameters. I found getopt, but it isn't supported in OS X. Can anyone tell me why getopt was implemented by BSD, but not GNU?
I tried building getopt in GNU C lib, but it failed for my poor skills with Linux.
Did anyone do this work?
There is a brew bottle for getopt.
Just run brew install gnu-getopt.
You can either specify the path for it like
/usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt
Or use brew link --force gnu-getopt so it will be linked in /usr/local/bin/
Just be aware that forcing linking might be corrupting your system (as it replaces the system getopt by the gnu one).
See maybe later answer suggesting to define FLAGS_GETOPT_CMD (though few comments state issues with it).
I recommend using Homebrew to install gnu-getopt and then adding $FLAGS_GETOPT_CMD to your ~/.bash_profile file to specify the cmd path for getopt, pointing at the homebrew location, like so:
brew install gnu-getopt
Then follow directions from brew to add to your local path:
sudo echo 'export PATH="/usr/local/opt/gnu-getopt/bin:$PATH"' >> ~/.bash_profile
Then you can add FLAGS_GETOPT_CMD:
sudo echo 'export FLAGS_GETOPT_CMD="$(brew --prefix gnu-getopt)/bin/getopt"' >> ~/.bash_profile
Open a new terminal, or run . ~/.bash_profile in existing terminal to load changes
Run echo $FLAGS_GETOPT_CMD to confirm it was actually set in your console
It's generally a better idea to use getopts instead, and stick with short options. You can see getopts in action in this StackOverflow Q&A. Short options are more standard throughout OSX command line tools, and consistency is a good thing.
Also, getopts is built in to bash, so it's definitely available in OSX, as well as every other platform that can run bash.
Note that there is a getopt is also available in OSX. From Terminal, type man getopt to see its documentation. It doesn't support long options. This is a good reason not to use long options when you're writing tools to run on OSX.
If you want to do this anyway, you can install getopt from macports. Alternately, if you want better portability, you can roll your own long argument handling.
Post some code, and we'll help debug it.

Resources