{"id":28955655,"url":"https://github.com/cvaniak/hoptex","last_synced_at":"2025-06-23T20:09:12.656Z","repository":{"id":191521843,"uuid":"678958797","full_name":"Cvaniak/Hoptex","owner":"Cvaniak","description":"EasyMotion/Hop like movement for TUI Framework Textual!","archived":false,"fork":false,"pushed_at":"2023-10-02T20:51:45.000Z","size":114,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-23T20:09:11.579Z","etag":null,"topics":["console","hop","keyboard","nomouse","python","reactive","terminal","textual","textualize","tui","vim"],"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/Cvaniak.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":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-15T19:33:01.000Z","updated_at":"2025-03-25T07:24:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"2ed361d2-1564-4122-9bd1-bb9ce1158a74","html_url":"https://github.com/Cvaniak/Hoptex","commit_stats":null,"previous_names":["cvaniak/hoptex"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Cvaniak/Hoptex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cvaniak%2FHoptex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cvaniak%2FHoptex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cvaniak%2FHoptex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cvaniak%2FHoptex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cvaniak","download_url":"https://codeload.github.com/Cvaniak/Hoptex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cvaniak%2FHoptex/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261548742,"owners_count":23175497,"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":["console","hop","keyboard","nomouse","python","reactive","terminal","textual","textualize","tui","vim"],"created_at":"2025-06-23T20:09:07.467Z","updated_at":"2025-06-23T20:09:12.636Z","avatar_url":"https://github.com/Cvaniak.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hoptex\n\nIf you are Vim user you heard about [EasyMotion](https://github.com/easymotion/vim-easymotion) and [Hop](https://github.com/phaazon/hop.nvim). This library is exactly this concept but for [Textual](https://github.com/Textualize/textual)!\nJust type your shortcut and focus/press widget you want. No mouse needed!\n\n\u003e Please always pin version of this library as API may change rapidly. It is experimental project and some staff may be modified.\n\n## Demo\n\n![DemoScreen](https://raw.githubusercontent.com/Cvaniak/Hoptex/master/documentation/DemoScreen.png)\n![HoptexScreen](https://raw.githubusercontent.com/Cvaniak/Hoptex/master/documentation/HoptexScreen.png)\n\n## Installation\n\nJust simply install via `pip`:\n\n```bash\npip3 install hoptex\n```\n\n## Documentation\n\n**Hoptex** allow to focus object and additionaly press it.\nBy default:\n\n- `space` will highlight `focusable` widgets and allow to focus choosen one\n- `ctrl+o` will focus and press widgets that are `focusable` and have `on_click` or `_on_click` method.\n\n### Usage\n\nThe most basic usage is just adding decorator on your **Textual** app like this:\n\n```python\nfrom textual.app import App\nfrom hoptex import hoptex\n\n@hoptex()\nclass NewTextualApp(App):\n    ...\n```\n\nThat is all. Super easy, right?\n\n### Allow and Block list\n\nTo choose which widgets will be highlighted **Hoptex** checks for three condition:\n\n- Widget have property `focusable=True`.\n- Widget is in allow list (then will be forced to be highlighted)\n- Widget is in blocked list (it have priority to exclude widget over allow list)\n\nThis parameters can be changed in `@hoptex` parameter `filter_lists` using `HoptexFilterWidgetsConfig`.\nBy default `allow_list` and `block_list` are empty and `include_focusable=True`.\nExample can be like this:\n\n```python\nfrom textual.demo import DemoApp, LocationLink  # Tested on Texutal 0.30.0 Demo App\nfrom textual.widgets import TextLog\nfrom hoptex import hoptex\nfrom hoptex.configs import HoptexWidgetsFiltersConfig\n\nwidgets_filters = HoptexWidgetsFiltersConfig(allow_list=[LocationLink], block_list=[TextLog])\n\n\n@hoptex(widgets_filters=widgets_filters)\nclass WrappedDemoApp(DemoApp):\n    ...\n\n```\n\n### Custom bindings\n\nIf you do not like default bindings you can change them with `HoptexBindingConfig`.\nIt has four fields, which you can replace with keybinding like in **Textual**:\n\n- `focus`, default to `space` -\u003e Run **Hoptex** screen to focus widget\n- `press`, default to `ctrl+p` -\u003e Run **Hoptex** screen to focus and press/click widget\n- `quit`, default to `escape` -\u003e Quits from **Hoptex** screen\n- `unfocus`, default to `escape` -\u003e Unfocuses from any widgets (if you are in e.x. text window, you need first to unfocus to use `space`)\n\nand also four config fields, that takes dictionary that will be injected in standard Binding field:\n\n- `focus_conf`, default to `{\"description\": \"Hop Focus\"}`\n- `press_conf`, default to `{\"description\": \"Hop Press\"}`\n- `quit_conf`, default to `{\"description\": \"Hop Quit\", \"show\": False}`\n- `unfocus_conf`, default to `{\"description\": \"Hop Unfocus\", \"show\": False}`\n\n```python\n\nfrom textual.demo import DemoApp\n\nfrom hoptex import hoptex\nfrom hoptex.configs import HoptexBindingConfig\n\nbindings = HoptexBindingConfig(press=\"ctrl+g\", press_conf={\"description\": \"Another description\"})\n\n\n@hoptex(bindings=bindings)\nclass DemoAppMy(DemoApp):\n    ...\n\n```\n\n### Custom Appearance\n\nYou can also inject custom label appearance, by `label` value. It should inherit from `Static`\nand allow for one argument (the letter that will be displayed).\nHowever easier way is to change CSS of `HopLabel`, which default is to:\n\n```css\nHopLabel {\n  width: 1;\n  height: 1;\n  color: yellow;\n  text-style: bold;\n  background: black;\n}\n```\n\n## TODO\n\n- Support more widgets on screen\n- Allow to use hoptex as wrapper for application (open any app with hoptex support)\n- If no place to jump, return\n- Color change\n- list of characters\n- custom Widget to mark\n- https://github.com/python/typing/issues/213\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcvaniak%2Fhoptex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcvaniak%2Fhoptex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcvaniak%2Fhoptex/lists"}