From 40ed5c1ecc22eeca59d0479bfc6df362771d2475 Mon Sep 17 00:00:00 2001 From: Christophe Dufaza Date: Sat, 24 Jun 2023 02:26:49 +0200 Subject: [PATCH] [rfc-dtsh 28/28]: west: west integration West command to open the devicetree shell (dtsh). West command implementation: - class dtsh in zephyr/scripts/west_commands/dtshell.py - packages dtsh and devicetree imported with os.sys.insert() statements Add dtsh extension to West in zephyr/scripts/west-commands.yml. Add dtsh's requirements to "used by west_commands" in zephyr/scripts/requirements-base.txt: - rich (https://github.com/Textualize/rich) - Pygments (https://github.com/pygments/pygments) Add support for West completion in: - zephyr/scripts/west_commands/completion/west-completion.bash - zephyr/scripts/west_commands/completion/west-completion.zsh Signed-off-by: Christophe Dufaza --- scripts/requirements-base.txt | 2 + scripts/west-commands.yml | 5 + .../completion/west-completion.bash | 1 + .../completion/west-completion.zsh | 1 + scripts/west_commands/dtshell.py | 109 ++++++++++++++++++ 5 files changed, 118 insertions(+) create mode 100644 scripts/west_commands/dtshell.py diff --git a/scripts/requirements-base.txt b/scripts/requirements-base.txt index 929a4de67d4cc47..ca8e39ed2a074a0 100644 --- a/scripts/requirements-base.txt +++ b/scripts/requirements-base.txt @@ -21,6 +21,8 @@ psutil pylink-square pyserial requests +rich +Pygments # for ram/rom reports anytree diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 5f63b44225c48f2..a65e40d24de6680 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -56,3 +56,8 @@ west-commands: - name: blobs class: Blobs help: work with binary blobs + - file: scripts/west_commands/dtshell.py + commands: + - name: dtsh + class: dtsh + help: devicetree shell diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index 48375cf486ac52d..9c1174efad8bade 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -956,6 +956,7 @@ __comp_west() zephyr-export spdx blobs + dtsh ) local cmds=(${builtin_cmds[*]} ${zephyr_ext_cmds[*]}) diff --git a/scripts/west_commands/completion/west-completion.zsh b/scripts/west_commands/completion/west-completion.zsh index 8cca9b5eee069a9..f291a19bf21a858 100644 --- a/scripts/west_commands/completion/west-completion.zsh +++ b/scripts/west_commands/completion/west-completion.zsh @@ -34,6 +34,7 @@ _west_cmds() { 'zephyr-export[export Zephyr installation as a CMake config package]' 'spdx[create SPDX bill of materials]' 'blobs[work with binary blobs]' + 'dtsh[devicetree shell]' ) local -a all_cmds=(${builtin_cmds} ${zephyr_ext_cmds}) diff --git a/scripts/west_commands/dtshell.py b/scripts/west_commands/dtshell.py new file mode 100644 index 000000000000000..fe149936e69984a --- /dev/null +++ b/scripts/west_commands/dtshell.py @@ -0,0 +1,109 @@ +# Copyright (c) 2023 Christophe Dufaza +# +# SPDX-License-Identifier: Apache-2.0 + +"""West command to open the devicetree shell (dtsh).""" + + +from typing import Optional, List + +import argparse +import os +import sys + +from west.commands import WestCommand +from west import log + +from zephyr_ext_common import ZEPHYR_SCRIPTS + + +# DtSh dependencies that are not installed within the West workspace's +# Python virtual environment. +sys.path.insert(0, str(ZEPHYR_SCRIPTS / "dts" / "python-devicetree" / "src")) +sys.path.insert(1, str(ZEPHYR_SCRIPTS / "dts" / "dtsh" / "src")) + +from dtsh.shell import DtShError +from dtsh.rich.session import DtShRichSession + + +DTSH_DESCRIPTION = """\ +Shell-like interface with a devicetree. + +- browse the devicetree through a familiar hierarchical file-system metaphor +- retrieve nodes and bindings with accustomed command names + and command line syntax +- generate simple documentation artifacts by redirecting commands output + to files (text, HTML, SVG) +- common command line interface paradigms (auto-completion, history) + and keybindings + +By default, dtsh will try to retrieve, or work out, the binding files +Zephyr has used at build-time to generate the DTS file, +or would use if it were to generate the DTS "now". +The --bindings-search-path option overrides this behavior by explicitly +setting the bindings search directories: + + $ west dtsh --bindings-search-path dir1:dir2 zephyr.dts + +Note: the path separator is platform-dependent (";" on Ms Windows, +":" anywhere else). + +If the command line does not specify a DTS file path, +dtsh will try to open the devicetree at build/zephy/zephyr.dts, +allowing for a simple work-flow: + + $ west build + $ west dtsh + +""" + + +class dtsh(WestCommand): + """Devicetree shell West command.""" + + def __init__(self) -> None: + super().__init__( + "dtsh", "devicetree shell", DTSH_DESCRIPTION, accepts_unknown_args=False + ) + + def do_add_parser(self, parser_adder): + parser = parser_adder.add_parser( + self.name, + help=self.help, + formatter_class=argparse.RawDescriptionHelpFormatter, + description=self.description, + ) + parser.add_argument( + "--bindings-search-path", + help="directories to search for the binding files", + required=False, + nargs=1, + metavar="PATH", + ) + parser.add_argument( + "dts", + help="path to the Devicetree source file", + nargs="?", + metavar="DTS", + default="build/zephyr/zephyr.dts", + ) + + return parser + + def do_run(self, args, unknown) -> None: + del unknown # Unused. + dts: str = args.dts + binding_dirs: Optional[List[str]] = ( + args.bindings_search_path[0].split(os.path.pathsep) + if args.bindings_search_path + else None + ) + + try: + # Initialize DT model, shell, etc. + session = DtShRichSession.create(dts, binding_dirs) + except DtShError as e: + log.die(e.msg) + + # Enter the devicetree shell interactive session loop. + session.run()