Skip to content
/ Hoptex Public

EasyMotion/Hop like movement for TUI Framework Textual!

License

Notifications You must be signed in to change notification settings

Cvaniak/Hoptex

Repository files navigation

Hoptex

If you are Vim user you heard about EasyMotion and Hop. This library is exactly this concept but for Textual! Just type your shortcut and focus/press widget you want. No mouse needed!

Please always pin version of this library as API may change rapidly. It is experimental project and some staff may be modified.

Demo

DemoScreen HoptexScreen

Installation

Just simply install via pip:

pip3 install hoptex

Documentation

Hoptex allow to focus object and additionaly press it. By default:

  • space will highlight focusable widgets and allow to focus choosen one
  • ctrl o will focus and press widgets that are focusable and have on_click or _on_click method.

Usage

The most basic usage is just adding decorator on your Textual app like this:

from textual.app import App
from hoptex import hoptex

@hoptex()
class NewTextualApp(App):
    ...

That is all. Super easy, right?

Allow and Block list

To choose which widgets will be highlighted Hoptex checks for three condition:

  • Widget have property focusable=True.
  • Widget is in allow list (then will be forced to be highlighted)
  • Widget is in blocked list (it have priority to exclude widget over allow list)

This parameters can be changed in @hoptex parameter filter_lists using HoptexFilterWidgetsConfig. By default allow_list and block_list are empty and include_focusable=True. Example can be like this:

from textual.demo import DemoApp, LocationLink  # Tested on Texutal 0.30.0 Demo App
from textual.widgets import TextLog
from hoptex import hoptex
from hoptex.configs import HoptexWidgetsFiltersConfig

widgets_filters = HoptexWidgetsFiltersConfig(allow_list=[LocationLink], block_list=[TextLog])


@hoptex(widgets_filters=widgets_filters)
class WrappedDemoApp(DemoApp):
    ...

Custom bindings

If you do not like default bindings you can change them with HoptexBindingConfig. It has four fields, which you can replace with keybinding like in Textual:

  • focus, default to space -> Run Hoptex screen to focus widget
  • press, default to ctrl p -> Run Hoptex screen to focus and press/click widget
  • quit, default to escape -> Quits from Hoptex screen
  • unfocus, default to escape -> Unfocuses from any widgets (if you are in e.x. text window, you need first to unfocus to use space)

and also four config fields, that takes dictionary that will be injected in standard Binding field:

  • focus_conf, default to {"description": "Hop Focus"}
  • press_conf, default to {"description": "Hop Press"}
  • quit_conf, default to {"description": "Hop Quit", "show": False}
  • unfocus_conf, default to {"description": "Hop Unfocus", "show": False}
from textual.demo import DemoApp

from hoptex import hoptex
from hoptex.configs import HoptexBindingConfig

bindings = HoptexBindingConfig(press="ctrl g", press_conf={"description": "Another description"})


@hoptex(bindings=bindings)
class DemoAppMy(DemoApp):
    ...

Custom Appearance

You can also inject custom label appearance, by label value. It should inherit from Static and allow for one argument (the letter that will be displayed). However easier way is to change CSS of HopLabel, which default is to:

HopLabel {
  width: 1;
  height: 1;
  color: yellow;
  text-style: bold;
  background: black;
}

TODO

  • Support more widgets on screen
  • Allow to use hoptex as wrapper for application (open any app with hoptex support)
  • If no place to jump, return
  • Color change
  • list of characters
  • custom Widget to mark
  • python/typing#213