{"id":21034661,"url":"https://github.com/lpenz/ptvertmenu","last_synced_at":"2025-07-14T18:17:35.349Z","repository":{"id":204174152,"uuid":"711262211","full_name":"lpenz/ptvertmenu","owner":"lpenz","description":"Vertical menu widget for prompt-toolkit with optional fzf-inspired search","archived":false,"fork":false,"pushed_at":"2024-02-17T19:25:48.000Z","size":790,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-30T10:04:18.461Z","etag":null,"topics":["menu","prompt-toolkit","python-prompt-toolkit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lpenz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-10-28T17:41:11.000Z","updated_at":"2024-07-31T13:45:33.000Z","dependencies_parsed_at":"2023-11-26T19:35:52.239Z","dependency_job_id":"3a0890fd-7bdf-45b1-892e-b7e0eff10c43","html_url":"https://github.com/lpenz/ptvertmenu","commit_stats":null,"previous_names":["lpenz/ptvertmenu"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/lpenz/ptvertmenu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpenz%2Fptvertmenu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpenz%2Fptvertmenu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpenz%2Fptvertmenu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpenz%2Fptvertmenu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lpenz","download_url":"https://codeload.github.com/lpenz/ptvertmenu/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpenz%2Fptvertmenu/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265328743,"owners_count":23747945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["menu","prompt-toolkit","python-prompt-toolkit"],"created_at":"2024-11-19T13:07:55.755Z","updated_at":"2025-07-14T18:17:35.302Z","avatar_url":"https://github.com/lpenz.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/lpenz/ptvertmenu/actions/workflows/ci.yml/badge.svg)](https://github.com/lpenz/ptvertmenu/actions/workflows/ci.yml)\n[![coveralls](https://coveralls.io/repos/github/lpenz/ptvertmenu/badge.svg?branch=main)](https://coveralls.io/github/lpenz/ptvertmenu?branch=main)\n[![PyPI](https://img.shields.io/pypi/v/ptvertmenu)](https://pypi.org/project/ptvertmenu/)\n[![github](https://img.shields.io/github/v/release/lpenz/disk-img-tool?logo=github)](https://github.com/lpenz/disk-img-tool/releases)\n\n\n# ptvertmenu\n\nVertical menu widget for the excellent [prompt-toolkit], with optional\nfzf-inspired search\n\nThis is a demo of the included [ptvertmenu-man](src/bin/ptvertmenu-man) utility:\n\n![demo-man](demos/demo-man.gif)\n\n\n## Getting started\n\nThe example below creates a menu that shows the contents of files and\ndirectories as the cursor goes over them, with full mouse support:\n\n```.py\n#!/usr/bin/env python3\n\"\"\"\nLook at files in the current directory\n\"\"\"\n\nimport os\nfrom typing import Optional, Any\n\nimport ptvertmenu\nfrom prompt_toolkit import Application\nfrom prompt_toolkit.key_binding import KeyBindings\nfrom prompt_toolkit.key_binding.bindings.focus import focus_next\nfrom prompt_toolkit.key_binding.key_processor import KeyPressEvent\nfrom prompt_toolkit.layout.containers import VSplit\nfrom prompt_toolkit.layout.layout import Layout\nfrom prompt_toolkit.styles import Style\nfrom prompt_toolkit.widgets import Frame, TextArea\n\nE = KeyPressEvent\n\n\ndef showfile(contents: TextArea, item: Optional[tuple[str, Any]], index: int) -\u003e None:\n    assert item\n    name = item[1]\n    try:\n        if os.path.isdir(name):\n            contents.text = '\\n'.join(os.listdir(name))\n        else:\n            with open(name, \"r\", encoding=\"utf-8\", errors=\"replace\") as fd:\n                contents.text = fd.read()\n    except Exception as exc:\n        contents.text = f\"Error: {exc}\"\n\n\ndef main() -\u003e None:\n    files = [(f, f) for f in os.listdir(\".\")]\n    contents = TextArea(text=\"\", multiline=True, wrap_lines=True, read_only=True)\n    menu = ptvertmenu.VertMenu(\n        items=files,\n        selected_handler=lambda item, index: showfile(contents, item, index),\n    )\n    root_container = VSplit(\n        [\n            Frame(title=\"Files\", body=menu),\n            Frame(title=\"Contents\", body=contents),\n        ]\n    )\n    layout = Layout(root_container)\n    style = Style.from_dict({\"vertmenu.selected\": \"reverse\"})\n    kb = KeyBindings()\n\n    @kb.add(\"tab\")\n    def tab(event: E) -\u003e None:\n        focus_next(event)\n\n    @kb.add(\"c-d\")\n    @kb.add(\"c-c\")\n    def close(event: E) -\u003e None:\n        app.exit()\n\n    app: Application[None] = Application(\n        layout=layout,\n        full_screen=True,\n        style=style,\n        key_bindings=kb,\n        mouse_support=True,\n    )\n    app.run()\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\n## Installation\n\n\n### Releases\n\nptvertmenu can be installed via [pypi]:\n\n```\npip install ptvertmenu\n```\n\nFor [nix] users, it is also available as a [flake].\n\n\n### Repository\n\nWe can also clone the github repository and install ptvertmenu from it with:\n\n```\npip install .\n```\n\nWe can also install it for the current user only by running instead:\n\n```\npip install --user .\n```\n\n\n## Development\n\nptvertmenu uses the standard python3 infra. To develop and test the module:\n- Clone the repository and go into the directory:\n  ```\n  git clone git@github.com:lpenz/ptvertmenu.git\n  cd ptvertmenu\n  ```\n- Use [`venv`] to create a local virtual environment with\n  ```\n  python -m venv venv\n  ```\n- Activate the environment by running the shell-specific `activate`\n  script in `./venv/bin/`. For [fish], for instance, run:\n  ```\n  source ./venv/bin/activate.fish\n  ```\n- Install ptvertmenu in \"editable mode\":\n  ```\n  pip install -e '.[test]'\n  ```\n- To run the tests:\n  ```\n  pytest\n  ```\n  Or, to run the tests with coverage:\n  ```\n  pytest --cov\n  ```\n- Finally, to exit the environment and clean it up:\n  ```\n  deactivate\n  rm -rf venv\n  ```\n\n\n[pypi]: https://pypi.org/project/ptvertmenu/\n[nix]: https://nixos.org/\n[flake]: https://nixos.wiki/wiki/Flakes\n[`venv`]: https://docs.python.org/3/library/venv.html\n[prompt-toolkit]: https://github.com/prompt-toolkit/python-prompt-toolkit\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpenz%2Fptvertmenu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flpenz%2Fptvertmenu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpenz%2Fptvertmenu/lists"}