1#compdef west
2
3# Copyright (c) 2022 Nordic Semiconductor ASA
4# SPDX-License-Identifier: Apache-2.0
5
6# Ensure this works also when being source-ed
7compdef _west west
8
9typeset -A -g _opt_args
10
11_west_cmds() {
12  local -a builtin_cmds=(
13  'init[create a west workspace]'
14  'update[update projects described in west manifest]'
15  'list[print information about projects]'
16  'manifest[manage the west manifest]'
17  'diff["git diff" for one or more projects]'
18  'status["git status" for one or more projects]'
19  'forall[run a command in one or more local projects]'
20  'config[get or set config file values]'
21  'topdir[print the top level directory of the workspace]'
22  'help[get help for west or a command]'
23  )
24
25  local -a zephyr_ext_cmds=(
26  'completion[display shell completion scripts]'
27  'boards[display information about supported boards]'
28  'build[compile a Zephyr application]'
29  'sign[sign a Zephyr binary for bootloader chain-loading]'
30  'flash[flash and run a binary on a board]'
31  'debug[flash and interactively debug a Zephyr application]'
32  'debugserver[connect to board and launch a debug server]'
33  'attach[interactively debug a board]'
34  'zephyr-export[export Zephyr installation as a CMake config package]'
35  'spdx[create SPDX bill of materials]'
36  'blobs[work with binary blobs]'
37  'sdk[manage SDKs]'
38  )
39
40  local -a all_cmds=(${builtin_cmds} ${zephyr_ext_cmds})
41
42  if [[ -v WEST_COMP_CHECK_WORKSPACE ]]; then
43    west topdir &>/dev/null
44    if [ $? -eq 0 ]; then
45      _values "west command" $all_cmds
46    else
47      _values "west command" $builtin_cmds
48    fi
49  else
50      _values "west command" $all_cmds
51  fi
52}
53
54# Completion script for Zephyr's meta-tool, west
55_west() {
56
57
58  # Global options for all commands
59  local -a global_opts=(
60  # (: * -) as exclusion list means exclude everything else
61  '(: * -)'{-h,--help}'[show help]'
62  # An exclusion list with the very option means only allow once
63  {-v,--verbose}'[enable verbosity]'
64  '(: * -)'{-V,--version}'[print version]'
65  '(-z --zephyr-base)'{-z,--zephyr-base}'[zephyr base folder]:zephyr base folder:_directories'
66  )
67
68  typeset -A opt_args
69  local curcontext="$curcontext" context state state_descr line
70  local -a orig_words
71
72  orig_words=( ${words[@]} )
73
74  _arguments -S -C \
75    $global_opts \
76          "1: :->cmds" \
77          "*::arg:->args" \
78
79  case "$state" in
80  cmds)
81    _west_cmds
82    ;;
83
84  args)
85    _opt_args=( ${(@kv)opt_args} )
86    _call_function ret _west_$line[1]
87    ;;
88  esac
89}
90
91__west_x()
92{
93  west 2>/dev/null "$@"
94}
95
96_get_west_projs() {
97  local extra_args
98  [[ -v _opt_args[-z] ]] && extra_args="-z $_opt_args[-z]"
99  [[ -v _opt_args[--zephyr-base] ]] && extra_args="-z $_opt_args[--zephyr-base]"
100
101  _west_projs=($(__west_x $extra_args list --format={name}))
102  _describe 'projs' _west_projs
103}
104
105_get_west_boards() {
106  _west_boards=( $(__west_x boards --format='{name}|{qualifiers}') )
107  for i in {1..${#_west_boards[@]}}; do
108    local name="${_west_boards[$i]%%|*}"
109    local transformed_board="${_west_boards[$i]//|//}"
110    _west_boards[$i]="${transformed_board//,/ ${name}/}"
111  done
112  _west_boards=(${(@s/ /)_west_boards})
113
114  _describe 'boards' _west_boards
115}
116
117_west_init() {
118  local -a opts=(
119  '(-l --local)'{--mr,--manifest-rev}'[manifest revision]:manifest rev:'
120  {--mf,--manifest-file}'[manifest file]:manifest file:'
121  '(-l --local)'{-m,--manifest}'[manifest URL]:manifest URL:_directories'
122  '(-m --manifest --mr --manifest-rev)'{-l,--local}'[use local directory as manifest repository]:local manifest repository directory:_directories'
123  )
124
125  _arguments -S $opts \
126          "1:workspace directory:"
127}
128
129_west_update() {
130  local -a opts=(
131  '--stats[print performance stats]'
132  '--name-cache[name-based cache]:name cache folder:_directories'
133  '--path-cache[path-based cache]:path cache folder:_directories'
134  {-f,--fetch}'[fetch strategy]:fetch strategy:(always smart)'
135  {-o,--fetch-opt}'[fetch options]:fetch options:'
136  {-n,--narrow}'[narrow fetch]'
137  {-k,--keep-descendants}'[keep manifest-rev descendants checked out]'
138  {-r,--rebase}'[rebase checked out branch onto the new manifest-rev]'
139  )
140
141  _arguments -S $opts \
142      "1:west proj:_get_west_projs"
143}
144
145_west_list() {
146  local -a opts=(
147  {-a,--all}'[include inactive projects]'
148  '--manifest-path-from-yaml[print performance stats]'
149  {-f,--format}'[format string]:format string:'
150  )
151
152  _arguments -S $opts \
153      "1:west proj:_get_west_projs"
154}
155
156_west_manifest() {
157  local -a opts=(
158  '--resolve[resolve into single manifest]'
159  '--freeze[resolve into single manifest, with SHAs]'
160  '--validate[silently validate manifest]'
161  '--path[print the path to the top level manifest file]'
162  {-o,--out}'[output file]:output file:_files'
163  )
164
165  _arguments -S $opts
166}
167
168_west_diff() {
169  local -a opts=(
170  {-a,--all}'[include inactive projects]'
171  )
172
173  _arguments -S $opts \
174      "1:west proj:_get_west_projs"
175}
176
177_west_status() {
178  local -a opts=(
179  {-a,--all}'[include inactive projects]'
180  )
181
182  _arguments -S $opts \
183      "1:west proj:_get_west_projs"
184}
185
186_west_forall() {
187  local -a opts=(
188  '-c[command to execute]:command:'
189  {-a,--all}'[include inactive projects]'
190  )
191
192  _arguments -S $opts \
193      "1:west proj:_get_west_projs"
194}
195
196_west_config() {
197  local -a opts=(
198  {-l,--list}'[list all options and values]'
199  {-d,--delete}'[delete an option in one config file]'
200  {-D,--delete-all}"[delete an option everywhere it\'s set]"
201  + '(mutex)'
202  '--system[system-wide file]'
203  '--global[global user-wide file]'
204  "--local[this workspace\'s file]"
205  )
206
207  _arguments -S $opts
208}
209
210_west_help() {
211  _west_cmds
212}
213
214_west_completion() {
215
216  _arguments -S "1:shell:(bash zsh fish)"
217}
218
219_west_boards() {
220  local -a opts=(
221  {-f,--format}'[format string]:format string:'
222  {-n,--name}'[name regex]:regex:'
223  '*--arch-root[Add an arch root]:arch root:_directories'
224  '*--board-root[Add a board root]:board root:_directories'
225  '*--soc-root[Add a soc root]:soc root:_directories'
226  )
227
228  _arguments -S $opts
229}
230
231_west_build() {
232  local -a opts=(
233  '(-b --board)'{-b,--board}'[board to build for]:board:_get_west_boards'
234  '(-d --build-dir)'{-d,--build-dir}'[build directory to create or use]:build dir:_directories'
235  '(-f --force)'{-f,--force}'[ignore errors and continue]'
236  '--sysbuild[create multi-domain build system]'
237  '--no-sysbuild[do not create multi-domain build system]'
238  '(-c --cmake)'{-c,--cmake}'[force a cmake run]'
239  '--cmake-only[just run cmake]'
240  '--domain[execute build tool (make or ninja) for a given domain]:domain:'
241  '(-t --target)'{-t,--target}'[run build system target]:target:'
242  '(-T --test-item)'{-T,--test-item}'[Build based on test data in .yml]:test item:'
243  {-o,--build-opt}'[options to pass to build tool (make or ninja)]:tool opt:'
244  '(-n --just-print --dry-run --recon)'{-n,--just-print,--dry-run,--recon}"[just print build commands, don't run them]"
245  '(-p --pristine)'{-p,--pristine}'[pristine build setting]:pristine:(auto always never)'
246  )
247  _arguments -S $opts \
248      "1:source_dir:_directories"
249}
250
251_west_sign() {
252  local -a opts=(
253  '(-d --build-dir)'{-d,--build-dir}'[build directory to create or use]:build dir:_directories'
254  '(-q --quiet)'{-q,--quiet}'[suppress non-error output]'
255  '(-f --force)'{-f,--force}'[ignore errors and continue]'
256  '(-t --tool)'{-t,--tool}'[image signing tool name]:tool:(imgtool rimage)'
257  '(-p --tool-path)'{-p,--tool-path}'[path to the tool]:tool path:_directories'
258  '(-D --tool-data)'{-D,--tool-data}'[path to tool data]:tool data path:_directories'
259  '(--no-bin)--bin[produce a signed bin file]'
260  '(--bin)--no-bin[do not produce a signed bin file]'
261  '(-B --sbin)'{-B,--sbin}'[signed .bin filename]:bin filename:_files'
262  '(--no-hex)--hex[produce a signed hex file]'
263  '(--hex)--no-hex[do not produce a signed hex file]'
264  '(-H --shex)'{-H,--shex}'[signed .hex filename]:hex filename:_files'
265  )
266
267  _arguments -S $opts
268}
269
270typeset -a -g _west_runner_opts=(
271  '(-H --context)'{-H,--context}'[print runner-specific options]'
272  '--board-dir[board directory]:board dir:_directories'
273  '(-f --file)'{-f,--file}'[path to binary]:path to binary:_files'
274  '(-t --file-type)'{-t,--file-type}'[type of binary]:type of binary:(hex bin elf)'
275  '--elf-file[path to zephyr.elf]:path to zephyr.elf:_files'
276  '--hex-file[path to zephyr.hex]:path to zephyr.hex:_files'
277  '--bin-file[path to zephyr.bin]:path to zephyr.bin:_files'
278  '--gdb[path to GDB]:path to GDB:_files'
279  '--openocd[path to openocd]:path to openocd:_files'
280  '--openocd-search[path to add to openocd search path]:openocd search:_directories'
281)
282
283_west_flash() {
284  local -a opts=(
285  '(-d --build-dir)'{-d,--build-dir}'[build directory to create or use]:build dir:_directories'
286  '(-r --runner)'{-r,--runner}'[override default runner from build-dir]:runner:'
287  '--skip-rebuild[do not refresh cmake dependencies first]'
288  '--domain[execute build tool (make or ninja) for a given domain]:domain:'
289  )
290
291  local -a all_opts=(${_west_runner_opts} ${opts})
292  _arguments -S $all_opts
293}
294
295_west_debug() {
296  _west_flash
297}
298
299_west_debugserver() {
300  _west_flash
301}
302
303_west_attach() {
304  _west_flash
305}
306
307_west_spdx() {
308  local -a opts=(
309  '(-i --init)'{-i,--init}'[initialize CMake file-based API]'
310  '(-d --build-dir)'{-d,--build-dir}'[build directory to create or use]:build dir:_directories'
311  '(-n --namespace-prefix)'{-n,--namespace-prefix}'[namespace prefix]:namespace prefix:'
312  '(-s --spdx-dir)'{-s,--spdx-dir}'[SPDX output directory]:spdx output dir:_directories'
313  '--analyze-includes[also analyze included header files]'
314  '--include-sdk[also generate SPDX document for SDK]'
315  )
316  _arguments -S $opts
317}
318
319_west_blobs() {
320  local -a blob_cmds=(
321  'list[list binary blobs]'
322  'fetch[fetch binary blobs]'
323  'clean[clean working tree of binary blobs]'
324  )
325
326  local line state
327
328  _arguments -S -C \
329          "1: :->cmds" \
330          "*::arg:->args" \
331
332  case "$state" in
333  cmds)
334    _values "west blob cmds" $blob_cmds
335    ;;
336
337  args)
338    _opt_args=( ${(@kv)opt_args} )
339    _call_function ret _west_blob_$line[1]
340    ;;
341  esac
342}
343
344_west_blob_list () {
345  local -a opts=(
346  {-f,--format}'[format string]:format string:'
347  )
348
349  _arguments -S $opts \
350      "1:west proj:_get_west_projs"
351}
352
353_west_blob_fetch () {
354  _arguments -S "1:west proj:_get_west_projs"
355}
356
357_west_blob_clean () {
358  _arguments -S "1:west proj:_get_west_projs"
359}
360
361# don't run the completion function when being source-ed or eval-ed
362if [ "$funcstack[1]" = "_west" ]; then
363    _west
364fi
365