Bash completion for Maven escapes colon - bash

I added bash completion for Maven following the docs:
http://maven.apache.org/guides/mini/guide-bash-m2-completion.html
Everything works well except for goals that use a colon. For instance, instead of
mvn eclipse:eclipse
completion escapes the colon
mvn eclipse\:eclipse
Any suggestions how this can be fixed? I'm using Ubuntu 8.10 (2.6.27-17-generic) and
$ bash -version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)

From Bash FAQ E13.
Just after the complete command in the script you linked to, issue this command to remove the colon from the list of completion word break characters:
COMP_WORDBREAKS=${COMP_WORDBREAKS//:}

Here is a related question and another suggested solution:
How to reset COMP_WORDBREAKS without effecting other completion script?
As stated before, the simplest solution is to alter COMP_WORDBREAKS. However, modifying COMP_WORDBREAKS in your completion script is not safe (as it is a global variable and it has the side effect of affecting the behavior of other completion scripts - for example scp).
Therefore, bash completion offers some helper methods which you can use to achieve your goal in a better and more safer way.
Two helper methods were added in Bash completion 1.2 for this:
_get_comp_words_by_ref with the -n EXCLUDE option
gets the word-to-complete without considering the characters in EXCLUDE as word breaks
__ltrim_colon_completions
removes colon containing prefix from COMPREPLY items
(a workaround for http://tiswww.case.edu/php/chet/bash/FAQ - E13)
So, here is a basic example of how to a handle a colon (:) in completion words:
_mytool()
{
local cur
_get_comp_words_by_ref -n : cur
# my implementation here
__ltrim_colon_completions "$cur"
}
complete -F _mytool mytool
Using the helper methods also simplifies the completion script and ensures that you get the same behavior on any environment (bash-3 or bash-4).
You can also take a look at man or perl completion scripts in /etc/bash_completion.d to see how they use the above helper methods to solve this problem.

Any suggestions how this can be fixed? I'm using Ubuntu 8.10 (2.6.27-17-generic) and
Dennis answer is definitely correct.
But for the record, there is a logged issue (MNG-3928) to improve the documentation about the Maven integration with bash. The issue has a script attached which is an improved version of the one currently online and just works. You might want to give it a try.
Personally, I use the Bash Completion script from Ludovic Claude's PPA (the one that is bundled into the maven package from Ubuntu) that I download directly from bazaar (her e is a direct download link to the HEAD revision). It is just awesome.

I'd go with the Maven2 Bash Completion File at willcodeforbeer.com.
works great
handles colons
doesn't muck up global variable COMP_WORDBREAKS (thereby breaking scp, etc)
easy to edit and understand
Hope that helps!

Related

How do I use the script's directory in Bash? [duplicate]

Is there a less brute-force way to do this?
#!/bin/ksh
THIS_SCRIPT=$(/usr/bin/readlink -f $(echo $0 | /bin/sed "s,^[^/],$PWD/&,"))
echo $THIS_SCRIPT
I'm stuck using ksh but would prefer a solution that works in bash too (which I think this does).
Entry #28 in the bash FAQ:
How do I determine the location of my script? I want to read some config files from the same place.
There are two prime reasons why this issue comes up: either you want to externalize data or configuration of your script and need a way to find these external resources, or your script is intended to act upon a bundle of some sort (eg. a build script), and needs to find the resources to act upon.
It is important to realize that in the general case, this problem has no solution. Any approach you might have heard of, and any approach that will be detailed below, has flaws and will only work in specific cases. First and foremost, try to avoid the problem entirely by not depending on the location of your script!
...
Using BASH_SOURCE
The BASH_SOURCE internal bash variable is actually an array of pathnames. If you expand it as a simple string, e.g. "$BASH_SOURCE", you'll get the first element, which is the pathname of the currently executing function or script.
I've always done:
SCRIPT_PATH=$(cd `dirname ${0}`; pwd)
I've never used readlink before: is it Gnu only? (i.e. will it work on HP-UX, AIX, and Solaris out of the box? dirname and pwd will....)
(edited to add `` which I forgot in original post. d'oh!)
(edit 2 to put on two lines which I've apparently always done when I look at previous scripts I'd written, but hadn't remembered properly. First call gets path, second call eliminates relative path)
(edit 3 fixed typo that prevented single line answer from working, back to single line!)
Why didn't I think to try this before I asked the question?
THIS_SCRIPT=$(/usr/bin/readlink -nf "$0")
Works great.
In macOS I use (edit: only works if you run the script from where the script actually is!)
my_script=$(pwd)/$(basename $0)

bash script overrides hard coded variables in executed second script

I'm calling Uncle. I'm attempting to manipulate variables that have hard coded values in a second bash script I am calling. I have no control over the script and am building a wrapper around it to adjust some build behavior before it finally kicks off a yocto build. I'm not sure what else to try after reading and trying numerous examples.
Examples of the situation:
build.sh calls build2.sh
IS_DEV=1 ./build2.sh #trying to override value
build2.sh
IS_DEV=0 # hardcoded value
echo $IS_DEV
# always results in 0.
I have also tried export IS_DEV=1 before calling build2.sh.
I'm sure this is pretty simple, but I cannot seem to get this to work. I appreciate any assistance. Is this possible? I'm using GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu) on Ubuntu 16.04.4 LTS.
Oh, I have also tried the sourcing technique with no luck.
IS_DEV=1 . ./build2.sh
IS_DEV=1 source ./build2.sh
Where am I getting this wrong?
Much appreciated.
If you can't modify the script, execute a modified version of it.
sed 's/^IS_DEV=0 /IS_DEV=1 /' build2.sh | sh
Obviously, pipe to bash if you need Bash semantics instead of POSIX sh semantics.
If the script really hard-codes a value with no means to override it from the command line, modifying that script is the only possible workaround. But the modification can be ephemeral; the above performs a simple substitution on the script, then passes the modified temporary copy through a pipe to a new shell instance for execution. The modification only exists in the pipeline, and doesn't affect the on-disk version of build2.sh.

Custom Bash Autocomplete with File Path Completion

I'm working on bash auto-completion for a project I'm the maintainer of. You can find the script here. I've cobbled this together with some hacking on my own, and with the help of some contributors who understand that completion APIs better than I do.
What we have works great -- with one exception. We can manage a completion like like this
//type
pestle.phar som[TAB]
//completes to
pestle.phar some-command-name
However, once we're here we lose file path/name completion that's a part of the stock bash shell. That is, working off the previous example, if a user types
//type
pestle.phar some-command-name /va[TAB]
we'd like it to complete to
//completes to the following, because var exists
pestle.phar some-command-name /var
Is there a way to just tell the complete command something like
Hey, in addition to everything we're telling you to do with our custom bash function, also keep your normal file path completion
If not, is there there some known science/boilerplate to reimplementing the file path completion in your own custom base completion functions?
Some other answers and the docs seem to indicate that the -o filenames or -o bashdefault options should take care of this -- but it doesn't seem to be working on OS X 10.11. I'm not sure if I misunderstand -o, or if the code in my completion files somehow overrides the -o behavior, or if OS X is doing it's I'm only a mostly well behaved unix thing.
Also -- if it's not obvious -- this is my first deep bash completion rodeo. If I've said something seemingly dumb/naive above please let me know. I may be looking for a fish right now, but I'd like to learn to fish in the bash completion river myself.
I think -o default (without -o filenames) should work for you. According to the manual:
bashdefault
Perform the rest of the default bash completions if the compspec generates no matches.
default
Use readline's default filename completion if the compspec generates no matches.
filenames
Tell readline that the compspec generates filenames, so it can perform any filename-specific processing (like adding a slash to directory
names, quoting special characters, or suppressing trailing spaces). Intended to be used with shell functions.
(Also see 'complete -d -o default cd' issue for the difference between -o default and -o bashdefault.)

Bash auto-completion highlighting

I'd like to know if it is possible to make bash auto-completion highlight the matched part of the auto-complete suggestion.
For example,
I am have directories with files such as these:
LSFJOB_647169535/ LSFJOB_647158534/
In this case, if I type LSF and hit Tab, then I get:
LSFJOB_6471
But then I have to focus hard to get which character should I type next.
I'd like bash to suggest me something like:
LSFJOB_647169535/ LSFJOB_647158534/
or
LSFJOB_647169535/ LSFJOB_647158534/
Do you know a way of doing it?
That is a good question!
Dennis Williamson already answered it there (SuperUser).
So it turns out that there is a "ReadLine Variable" that does exactly that: colored-completion-prefix.
Sadly it's only available in Bash v4.4 :c Link to the diff
You can check its value with bind -v|grep color
I tried to play with compgen but it appears that it strips colors away /:
Instead of colored-completion-prefix, which requires Bash 4.4, you could add the older (Bash 4.0)
set completion-prefix-display-length 2
to your ~/.inputrc (see manual). This replaces any common prefix longer than 2 characters with an ellipsis when showing the completions:
$ ls
LSFJOB_647158534 LSFJOB_647169535
$ cd LSFJOB_6471<tab>
...58534/ ...69535/

How to get the full pathname of the current shell script?

Is there a less brute-force way to do this?
#!/bin/ksh
THIS_SCRIPT=$(/usr/bin/readlink -f $(echo $0 | /bin/sed "s,^[^/],$PWD/&,"))
echo $THIS_SCRIPT
I'm stuck using ksh but would prefer a solution that works in bash too (which I think this does).
Entry #28 in the bash FAQ:
How do I determine the location of my script? I want to read some config files from the same place.
There are two prime reasons why this issue comes up: either you want to externalize data or configuration of your script and need a way to find these external resources, or your script is intended to act upon a bundle of some sort (eg. a build script), and needs to find the resources to act upon.
It is important to realize that in the general case, this problem has no solution. Any approach you might have heard of, and any approach that will be detailed below, has flaws and will only work in specific cases. First and foremost, try to avoid the problem entirely by not depending on the location of your script!
...
Using BASH_SOURCE
The BASH_SOURCE internal bash variable is actually an array of pathnames. If you expand it as a simple string, e.g. "$BASH_SOURCE", you'll get the first element, which is the pathname of the currently executing function or script.
I've always done:
SCRIPT_PATH=$(cd `dirname ${0}`; pwd)
I've never used readlink before: is it Gnu only? (i.e. will it work on HP-UX, AIX, and Solaris out of the box? dirname and pwd will....)
(edited to add `` which I forgot in original post. d'oh!)
(edit 2 to put on two lines which I've apparently always done when I look at previous scripts I'd written, but hadn't remembered properly. First call gets path, second call eliminates relative path)
(edit 3 fixed typo that prevented single line answer from working, back to single line!)
Why didn't I think to try this before I asked the question?
THIS_SCRIPT=$(/usr/bin/readlink -nf "$0")
Works great.
In macOS I use (edit: only works if you run the script from where the script actually is!)
my_script=$(pwd)/$(basename $0)

Resources