Generate & install completion scripts in build system
The previous commit added a means to generating the completion scripts and this one plugs that into the build system. A new build option 'install_completions' has been introduced. Set to 'True' by default. Completions for bash and fish use pkg-config for getting the preferred install locations for the completions. If the packages are not available, fallbacks are in-place. The 'completion' subdir has been kept to work around the ideology of Meson that does not allow creating/outputing files in subdirectories nor using the output of custom_target() in install_data(). https://github.com/containers/toolbox/pull/840
This commit is contained in:
		
							parent
							
								
									d69ce6794b
								
							
						
					
					
						commit
						bafbbe81c9
					
				|  | @ -43,3 +43,4 @@ database, etc.. | |||
| See our guides on | ||||
| [installing & getting started](https://containertoolbx.org/install/) with | ||||
| Toolbox and [Linux distro support](https://containertoolbx.org/distros/). | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,100 +0,0 @@ | |||
| # Check for bash | ||||
| [ -z "$BASH_VERSION" ] && return | ||||
| 
 | ||||
| __toolbox_containers() { | ||||
|   toolbox list -c 2>/dev/null | tail -n +2 2>/dev/null | cut -d " " -f 3 2>/dev/null | ||||
| } | ||||
| 
 | ||||
| __toolbox_distros() { | ||||
|   echo "fedora" | ||||
|   echo "rhel" | ||||
| } | ||||
| 
 | ||||
| __toolbox_images() { | ||||
|   toolbox list -i 2>/dev/null | tail -n +2 2>/dev/null | cut -d " " -f 3 2>/dev/null | ||||
| } | ||||
| 
 | ||||
| __toolbox() { | ||||
|   local MIN_VERSION=32 | ||||
|   local RAWHIDE_VERSION=34 | ||||
| 
 | ||||
|   local commands="create enter help init-container list rm rmi run" | ||||
|   local global_options="--assumeyes --help --log-level --log-podman" | ||||
|   local log_levels="debug info warn error fatal panic" | ||||
| 
 | ||||
|   declare -A options | ||||
|   local options=([create]="--distro --image --release" \ | ||||
|                  [enter]="--distro --release" \ | ||||
|                  [help]="$commands" \ | ||||
|                  [init-container]="--home --home-link --monitor-host --shell --uid --user" \ | ||||
| 		 [list]="--containers --images" \ | ||||
| 		 [rm]="--all --force" \ | ||||
| 		 [rmi]="--all --force" \ | ||||
| 		 [run]="--container --distro --release") | ||||
| 
 | ||||
|   _init_completion -s || return | ||||
| 
 | ||||
|   if [ "${COMP_CWORD}" -eq 1 ]; then | ||||
|     mapfile -t COMPREPLY < <(compgen -W "$global_options $commands" -- "$2") | ||||
|     return 0 | ||||
|   fi | ||||
| 
 | ||||
|   # If a global option is mentioned, don't mention it anymore | ||||
|   for option in $global_options; do | ||||
|     if [[ "${COMP_LINE}" =~ "$option" ]]; then | ||||
|       global_options="${global_options/$option}" | ||||
|     fi | ||||
|   done | ||||
| 
 | ||||
|   # If a command is mentioned, don't mention any more commands | ||||
|   local command | ||||
|   for cmd in $commands; do | ||||
|     if [[ "${COMP_LINE}" =~ "$cmd" ]]; then | ||||
|       commands="" | ||||
|       command="$cmd" | ||||
|     fi | ||||
|   done | ||||
| 
 | ||||
|   case "$prev" in | ||||
|     --assumeyes | -y | --help | -h | --verbose | -v | --log-podman) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "$global_options $commands" -- "$2") | ||||
|       return 0 | ||||
|       ;; | ||||
|     --container | -c) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_containers)" -- "$2") | ||||
|       return 0 | ||||
|       ;; | ||||
|     --distro | -d) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_distros)" -- "$2") | ||||
|       return 0 | ||||
|       ;; | ||||
|     --image | -i) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_images)" -- "$2") | ||||
|       return 0 | ||||
|       ;; | ||||
|     --release | -r) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "$(seq $MIN_VERSION $RAWHIDE_VERSION)" -- "$2") | ||||
|       return 0 | ||||
|       ;; | ||||
|     --log-level) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "$log_levels" -- "$2") | ||||
|       return 0 | ||||
|       ;; | ||||
|   esac | ||||
| 
 | ||||
|   local extra_comps | ||||
|   case "$command" in | ||||
|     rm | enter) | ||||
|       extra_comps="$(__toolbox_containers)" | ||||
|       ;;& | ||||
|     rmi) | ||||
|       extra_comps="$(__toolbox_images)" | ||||
|       ;;& | ||||
|     *) | ||||
|       mapfile -t COMPREPLY < <(compgen -W "${options[$command]} $extra_comps" -- "$2") | ||||
|       return 0; | ||||
|       ;; | ||||
|   esac | ||||
| } | ||||
| 
 | ||||
| complete -F __toolbox toolbox | ||||
|  | @ -0,0 +1,41 @@ | |||
| #!/usr/bin/env python3 | ||||
| # | ||||
| # Copyright © 2022 Ondřej Míchal | ||||
| # Copyright © 2022 Red Hat Inc. | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| # | ||||
| 
 | ||||
| import os | ||||
| import subprocess | ||||
| import sys | ||||
| 
 | ||||
| if len(sys.argv) != 3: | ||||
|     print('{}: wrong arguments'.format(sys.argv[0]), file=sys.stderr) | ||||
|     print('Usage: {} [SOURCE DIR] [COMPLETION TYPE]'.format(sys.argv[0]), file=sys.stderr) | ||||
|     print() | ||||
|     print("SOURCE DIR is path to the Toolbox Go source code") | ||||
|     print("COMPLETION TYPE is either 'bash', 'zsh' or 'fish'") | ||||
|     sys.exit(1) | ||||
| 
 | ||||
| source_dir = sys.argv[1] | ||||
| completion_type = sys.argv[2] | ||||
| 
 | ||||
| try: | ||||
|     os.chdir(source_dir) | ||||
|     output = subprocess.run(['go', 'run', '.', 'completion', completion_type], check=True) | ||||
| except subprocess.CalledProcessError as e: | ||||
|     print('{}: go run returned non-zero exit status {}'.format(sys.argv[0], e.returncode), file=sys.stderr) | ||||
|     sys.exit(e.returncode) | ||||
| 
 | ||||
| sys.exit(0) | ||||
|  | @ -0,0 +1,36 @@ | |||
| generate_completions_program = find_program('generate_completions.py') | ||||
| 
 | ||||
| if bash_completion.found() | ||||
|   bash_comp_dir = bash_completion.get_pkgconfig_variable('completionsdir') | ||||
| else | ||||
|   bash_comp_dir = get_option('datadir') / 'bash-completion' / 'completions' | ||||
|   message('bash-completion not found: using', get_option('prefix') / bash_comp_dir, 'as a falback install directory') | ||||
| endif | ||||
| 
 | ||||
| if fish.found() | ||||
|   fish_comp_dir = fish.get_pkgconfig_variable('completionsdir') | ||||
| else | ||||
|   fish_comp_dir = get_option('datadir') / 'fish' / 'completions' | ||||
|   message('fish not found: using', get_option('prefix') / fish_comp_dir, 'as a fallback install directory') | ||||
| endif | ||||
| 
 | ||||
| completion_bash = custom_target('bash-completion', | ||||
|   capture: true, | ||||
|   command: [generate_completions_program, meson.global_source_root() / 'src', 'bash'], | ||||
|   install: true, | ||||
|   install_dir: bash_comp_dir, | ||||
|   output: 'toolbox') | ||||
| 
 | ||||
| completion_zsh = custom_target('zsh-completion', | ||||
|   capture: true, | ||||
|   command: [generate_completions_program, meson.global_source_root() / 'src', 'zsh'], | ||||
|   install: true, | ||||
|   install_dir: get_option('datadir') / 'zsh' / 'site_functions', | ||||
|   output: '_toolbox') | ||||
| 
 | ||||
| completion_fish = custom_target('fish-completion', | ||||
|   capture: true, | ||||
|   command: [generate_completions_program, meson.global_source_root() / 'src', 'fish'], | ||||
|   install: true, | ||||
|   install_dir: fish_comp_dir, | ||||
|   output: 'toolbox.fish') | ||||
							
								
								
									
										11
									
								
								meson.build
								
								
								
								
							
							
						
						
									
										11
									
								
								meson.build
								
								
								
								
							|  | @ -19,6 +19,7 @@ shellcheck = find_program('shellcheck', required: false) | |||
| skopeo = find_program('skopeo', required: false) | ||||
| 
 | ||||
| bash_completion = dependency('bash-completion', required: false) | ||||
| fish = dependency('fish', required: false) | ||||
| 
 | ||||
| migration_path_for_coreos_toolbox = get_option('migration_path_for_coreos_toolbox') | ||||
| profiledir = get_option('profile_dir') | ||||
|  | @ -32,13 +33,6 @@ if tmpfilesdir == '' or not fs.exists('/run/.containerenv') | |||
|   endif | ||||
| endif | ||||
| 
 | ||||
| if bash_completion.found() | ||||
|   install_data( | ||||
|     'completion/bash/toolbox', | ||||
|     install_dir: bash_completion.get_variable(pkgconfig: 'completionsdir') | ||||
|   ) | ||||
| endif | ||||
| 
 | ||||
| if not skopeo.found() | ||||
|     message('Running system tests requires Skopeo for OCI image manipulation.') | ||||
| endif | ||||
|  | @ -70,5 +64,8 @@ subdir('data') | |||
| subdir('doc') | ||||
| subdir('profile.d') | ||||
| subdir('src') | ||||
| if get_option('install_completions') | ||||
|   subdir('completion') | ||||
| endif | ||||
| 
 | ||||
| meson.add_install_script('meson_post_install.py') | ||||
|  |  | |||
|  | @ -17,3 +17,10 @@ option( | |||
|   description: 'Directory for system-wide tmpfiles.d(5) files', | ||||
|   type: 'string', | ||||
| ) | ||||
| 
 | ||||
| option( | ||||
|   'install_completions', | ||||
|   description: 'Install bash, zsh and fish command completions', | ||||
|   type: 'boolean', | ||||
|   value: true, | ||||
| ) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue