ros2cli icon indicating copy to clipboard operation
ros2cli copied to clipboard

Autocomplete fails while using zsh.

Open evshary opened this issue 5 years ago • 26 comments

Bug report

Required Info:

  • Operating System:
    • Ubuntu 18.04
  • Installation type:
    • binaries
  • Version or commit hash:
    • Dashing / Eloquent
  • DDS implementation:
    • ALL
  • Client library (if applicable):
    • N/A

Steps to reproduce issue

I use zsh as my shell, but I find some problems while using <tab> to autocomplete.

  • While I type ros2 run <tab>, it works well.
  • However when I type ros2 run d<tab>, it can't show the packages which starts with 'd'.

Additional information

After some debugging, I find that the behavior is related to argcomplete library in Python 3. If I remove the library rm -rf ~/.local/lib/python3.6/site-packages/argcomplete*, zsh works well again. I'm not pretty sure what the root cause is. Maybe argcomplete library does not support zsh well.

evshary avatar Jun 13 '20 07:06 evshary

The fact that you have argcomplete under ~/.local/ indicates that you installed it via pip rather than (or in addition to) the Debian package.

Please share the version numbers of argcomplete reported by these two command:

  • pip3 freeze | grep arcomplete
  • dpkg -l | grep argcomplete

dirk-thomas avatar Jun 13 '20 15:06 dirk-thomas

@dirk-thomas You're right. I've install argcomplete with the command python3 -m pip install -U argcomplete according to the tutorial before.

My result for the two commands:

$ pip3 freeze | grep arcomplete
# Nothing output
$ dpkg -l | grep argcomplete
ii  python3-argcomplete                                 1.8.1-1ubuntu1                                  all          bash tab completion for argparse (for Python 3)
ii  python3-colcon-argcomplete                          0.3.3-1                                         all          Completion for colcon command lines using argcomplete.

I guess you want to see the version of argcomplete under ~/.local/

$ python3 -m pip freeze | grep argcomplete
argcomplete==1.11.1
colcon-argcomplete==0.3.3

evshary avatar Jun 14 '20 02:06 evshary

I can reproduce the problem with Eloquent (using 5.4.2-3ubuntu3.1). In Foxy it is working though (using 5.8-3ubuntu1).

I think this is a duplicate of kislyuk/argcomplete#258. Either you use a newer version of zsh or you have to patch the function _bash_complete manually (https://github.com/zsh-users/zsh/commit/e2f793e7df7214cc3d80e2fcfe961ed087c860ab):

  • type which _bash_complete

  • copy-n-past the whole function, but insert the -1 to the following line:

    • Before: (( COMP_POINT = 1 + ${#${(j. .)words[1,CURRENT]}} + $#QIPREFIX + $#IPREFIX + $#PREFIX ))
    • After: (( COMP_POINT = 1 + ${#${(j. .)words[1,CURRENT-1]}} + $#QIPREFIX + $#IPREFIX + $#PREFIX ))

dirk-thomas avatar Jun 15 '20 23:06 dirk-thomas

@j-rivero to work on getting a patch upstream.

dirk-thomas avatar Jun 16 '20 02:06 dirk-thomas

@dirk-thomas Thank you for the suggestion. The patch works perfectly!!! It frustrated me a long time about the argcomplete. You can close the issue if you think it's OK.

evshary avatar Jun 16 '20 03:06 evshary

You can close the issue if you think it's OK.

We will keep it open until it is tracked upstream.

dirk-thomas avatar Jun 16 '20 03:06 dirk-thomas

Hi! I have just installed ROS 2 (Galactic) for the first time on my machine (Ubuntu 20.04). I am also a user of ZSH, and for some reason the autocomplete isn't working; but it works on the Bash. Some more info:

➜  ~ zsh --version
zsh 5.8 (x86_64-ubuntu-linux-gnu)

➜  ~ which _bash_complete
_bash_complete () {
	local ret=1 
	local -a suf matches
	local -x COMP_POINT COMP_CWORD
	local -a COMP_WORDS COMPREPLY BASH_VERSINFO
	local -x COMP_LINE="$words" 
	local -A savejobstates savejobtexts
	(( COMP_POINT = 1 + ${#${(j. .)words[1,CURRENT-1]}} + $#QIPREFIX + $#IPREFIX + $#PREFIX ))
	(( COMP_CWORD = CURRENT - 1))
	COMP_WORDS=($words) 
	BASH_VERSINFO=(2 05b 0 1 release) 
	savejobstates=(${(kv)jobstates}) 
	savejobtexts=(${(kv)jobtexts}) 
	[[ ${argv[${argv[(I)nospace]:-0}-1]} = -o ]] && suf=(-S '') 
	matches=(${(f)"$(compgen $@ -- ${words[CURRENT]})"}) 
	if [[ -n $matches ]]
	then
		if [[ ${argv[${argv[(I)filenames]:-0}-1]} = -o ]]
		then
			compset -P '*/' && matches=(${matches##*/}) 
			compset -S '/*' && matches=(${matches%%/*}) 
			compadd -Q -f "${suf[@]}" -a matches && ret=0 
		else
			compadd -Q "${suf[@]}" -a matches && ret=0 
		fi
	fi
	if (( ret ))
	then
		if [[ ${argv[${argv[(I)default]:-0}-1]} = -o ]]
		then
			_default "${suf[@]}" && ret=0 
		elif [[ ${argv[${argv[(I)dirnames]:-0}-1]} = -o ]]
		then
			_directories "${suf[@]}" && ret=0 
		fi
	fi
	return ret
}

ferrolho avatar Sep 17 '21 15:09 ferrolho

@ferrolho I've tried the same patch in Galactic, and autocomplete doesn't work. I'm not really sure what happens, but maybe you can temporarily use Foxy instead.

evshary avatar Sep 22 '21 02:09 evshary

Hi, I'm having the same problem as @ferrolho with zsh version 5.8, and with both Foxy and Galaxy I'm unable to tab complete anything with the ros2 command.

I will add that zsh can tab complete parameters with any command except ros2. For example apt se<tab> will produce apt search, but ros2 lau<tab> will not complete to ros2 launch

paolotherocker avatar Oct 01 '21 07:10 paolotherocker

I meet the problem also both Foxy and Galactic. The patch didn’t work either. also zsh is 5.8,

CALMorACT avatar Oct 20 '21 08:10 CALMorACT

Having the same issue with ZSH and ROS2 Galactic.

Previously used ROS Noetic and tab auto-complete worked perfectly

RalphCodesTheInternet avatar Oct 26 '21 10:10 RalphCodesTheInternet

Having the same issue with Zsh and ROS2 Galactic too.

But I found a solution in https://kislyuk.github.io/argcomplete/#zsh-support

By adding these lines to .zshrc the argcompletion is succesfully enabled.

# argcomplete for ros2 & colcon
eval "$(register-python-argcomplete3 ros2)"
eval "$(register-python-argcomplete3 colcon)"

(Thanks to https://github.com/ros2/ros2cli/issues/534#issuecomment-957905035, I removed the unnessecary autoload -U bashcompinit \ bashcompinit)

image

chenjunnn avatar Nov 02 '21 13:11 chenjunnn

I have also been struggling with this argcomplete issue with ZSH and ROS2 Galactic for a long while. Thanks for the constructive suggestions in sink0918's comment. Actually I found that it's working by adding simply this in .zshrc: eval "$(register-python-argcomplete3 ros2)"

The arg completion for colcon was previously solved by sourcing colcon-argcomplete in .zshrc as described in colcon-Enable completion: source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.zsh

Shiyu-Liu avatar Nov 02 '21 16:11 Shiyu-Liu

Having the same issue with Zsh and ROS2 Galactic too.

But I found a solution in https://kislyuk.github.io/argcomplete/#zsh-support

By adding these lines to .zshrc the argcompletion is succesfully enabled.

# argcomplete for ros2 & colcon
autoload -U bashcompinit
bashcompinit
eval "$(register-python-argcomplete3 ros2)"
eval "$(register-python-argcomplete3 colcon)"

image

That worked for me, thanks for sharing!

paolotherocker avatar Nov 02 '21 16:11 paolotherocker

Huh, interesting. So it turns out that we are already calling eval "$(register-python-argcomplete ros2)" when sourcing for the zsh shell: https://github.com/ros2/ros2cli/blob/master/ros2cli/completion/ros2-argcomplete.zsh . And I verified locally that those files do indeed get sourced when source /opt/ros/rolling/setup.zsh. However, completion doesn't work anyway; you have to re-run the eval, as everyone above found out.

Actually, I found out that after sourcing /opt/ros/rolling/setup.zsh, it is enough to do:

complete -o nospace -o default -F _python_argcomplete "ros2"

That suggests to me that something else later in the sourcing process is unregistering what was already registered. Someone would need to look deeper into it to find out exactly why this isn't working as expected.

clalancette avatar Nov 02 '21 18:11 clalancette

Having the same issue with Zsh and ROS2 Galactic too.

But I found a solution in https://kislyuk.github.io/argcomplete/#zsh-support

By adding these lines to .zshrc the argcompletion is succesfully enabled.

# argcomplete for ros2 & colcon
eval "$(register-python-argcomplete3 ros2)"
eval "$(register-python-argcomplete3 colcon)"

(Thanks to #534 (comment), I removed the unnessecary autoload -U bashcompinit \ bashcompinit

image

Thank you a lot, I solve my problem by your sharing

CALMorACT avatar Nov 10 '21 09:11 CALMorACT

Instead of running eval "$(register-python-argcomplete3 ros2)" every time after sourcing setup.zsh, I made a modification in /opt/ros/galactic/share/rosidl_cli/environment/rosidl-argcomplete.zsh. I removed/commented the line:

autoload -U +X compinit && compinit

Then ros2 tab completion works. This has to do with compinit being called too many times (see also https://stackoverflow.com/questions/67136714/how-to-properly-call-compinit-and-bashcompinit-in-zsh ).

I'm not sure what a final fix should be, especially since tab completion for colcon still doesn't work with this change (the eval "$(register-python-argcomplete3 colcon)" is still needed for that).

frankkusters avatar Dec 08 '21 13:12 frankkusters

Hi, Is it possible to fix this issue before the humble release? :see_no_evil:

hardesh avatar May 04 '22 06:05 hardesh

Is it possible to fix this issue before the humble release? see_no_evil

Someone needs to debug it further, since we don't really understand the underlying cause. If you happen to find the problem and open a pull request, we're happy to review it.

clalancette avatar May 04 '22 12:05 clalancette

Aah got it. I don't have any previous experience with working on such an autocompletion tool. Are there any good resources to learn about this tool or any other autocompletion tool? I'd love to fix this issue. It's bugging me for a few days now After a quick google search, I did find a few stack overflow links but they weren't useful.

TIA

Edit: Found a setup tool doc in the README. Will start from there

hardesh avatar May 04 '22 13:05 hardesh

@hardesh I think I was on to something with compinit being called too often. What I hadn't tried to figure out is why compinit is being called in rosidl-argcomplete.zsh, where else it's being called, and what would be the right (single) spot to do it.

frankkusters avatar May 04 '22 13:05 frankkusters

@frankkusters I observed the same. compinit seems to clear previous complete commands. For example in my ROS environement I get the following:

$ complete -p

complete -o nospace -o default -F _python_argcomplete rosidl
complete -o nospace -o default -F _python_argcomplete ros2
complete -o nospace -o default -F _python_argcomplete ament_index
complete _bash bash
complete -o nospace -o default -F _python_argcomplete colcon

$ compinit

$ complete -p

complete _bash bash

AndreasR30 avatar Jun 21 '22 10:06 AndreasR30

For testing I removed the line autoload -U +X compinit && compinit from the following files:

/usr/share/colcon_argcomplete/hook/colcon-argcomplete.zsh
/opt/ros/humble/share/ros2cli/environment/ros2-argcomplete.zsh
/opt/ros/humble/share/ament_index_python/environment/ament_index-argcomplete.zsh
/opt/ros/humble/share/rosidl_cli/environment/rosidl-argcomplete.zsh

In order to make it work properly I have to add above line in my .zshrc before sourcing ROS workspace (and colcon-argcomplete). Whithout it it does not work. So it seems to be mandatory.

AndreasR30 avatar Jun 21 '22 10:06 AndreasR30

Should autoload -U +X compinit && compinit be removed from the ROS/colcon *argcomplete.zsh files then? To me it makes sense for these commands to reside in .zshrc - it's up to the zsh user if they want completion or not. For most people it will be enabled by default anyway.

frankkusters avatar Jun 22 '22 08:06 frankkusters

Maybe rather than removing the compinit call it should be replaced with a check and call? As far as I've tested, compinit sets the variable _comps, so it could be something like:

if (( ! ${+_comps} )); then
    autoload -U +X compinit && compinit
fi

This way neither completion script ordering nor the possible compinit call in .zshrc doesn't matter.

Edit: NVM had similar problem, but I'm not sure whether their solution works as intended - it calls compinit either way but with a flag (?), which doesn't change the fact that it clears previous completions.

mjbogusz avatar Jul 04 '22 14:07 mjbogusz

I am using Ubuntu 20.04 and Foxy, I have ZSH and oh-my-zsh installed. I needed to do the following to fix this issue.

pip install argcomplete
eval "$(register-python-argcomplete ros2)"
eval "$(register-python-argcomplete colcon)"

guzhaoyuan avatar Jul 22 '22 23:07 guzhaoyuan

Fixed by #750

gbiggs avatar Jan 13 '23 00:01 gbiggs

Having the same issue with Zsh and ROS2 Galactic too.

But I found a solution in https://kislyuk.github.io/argcomplete/#zsh-support

By adding these lines to .zshrc the argcompletion is succesfully enabled.

# argcomplete for ros2 & colcon
eval "$(register-python-argcomplete3 ros2)"
eval "$(register-python-argcomplete3 colcon)"

(Thanks to #534 (comment), I removed the unnessecary autoload -U bashcompinit \ bashcompinit)

image

Saved me! Thank you!!

almeida-allan avatar Aug 28 '23 01:08 almeida-allan