Skip to main content

Create rofi menus via python

Project description

Package version

rofi-menu

Rofi allows defining custom modes (see the spec).

This lib is a reference implementation with some extra "sugar".

Features:

  • simple menu definition via python
  • extendable
  • async in first place
  • allows keeping state during rofi session

Simple demo:

custom menu

Requirements

  • rofi >= 1.5.4
  • python >= 3.6

Installation

Using pip

$ pip install rofi-menu

Example

Create a python script which will be used for rofi mode e.g. example.py (don't forget to mark it as executable -- chmod +x ./example.py)

Assuming you installed rofi-menu into a virtual environment (let's say it's ~/.pyenv/versions/rofi/bin/python). Make sure shebang points to the right python executable, e.g. #!/home/user/pyenv/versions/rofi/bin/python.

#!/home/user/.pyenv/versions/rofi/bin/python
import rofi_menu


class ProjectsMenu(rofi_menu.Menu):
    prompt = "Projects"
    items = [
        rofi_menu.BackItem(),
        rofi_menu.ShellItem("Project 1", "code-insiders ~/Develop/project1"),
        rofi_menu.ShellItem("Project 2", "code-insiders ~/Develop/project2"),
        rofi_menu.ShellItem("Project X", "code-insiders ~/Develop/projectx"),
    ]


class LogoutMenu(rofi_menu.Menu):
    prompt = "Logout"
    items = [
        rofi_menu.ShellItem("Yes", "i3-msg exit", flags={rofi_menu.FLAG_STYLE_URGENT}),
        rofi_menu.ExitItem("No", flags={rofi_menu.FLAG_STYLE_ACTIVE}),
    ]


class MainMenu(rofi_menu.Menu):
    prompt = "menu"
    items = [
        rofi_menu.TouchpadItem(),
        rofi_menu.NestedMenu("Projects >", ProjectsMenu()),
        rofi_menu.ShellItem(
            "Downloads (show size)", "du -csh ~/Downloads", show_output=True
        ),
        rofi_menu.NestedMenu("Second monitor", rofi_menu.SecondMonitorMenu()),
        rofi_menu.ShellItem("Lock screen", "i3lock -i ~/.config/i3/bg.png"),
        rofi_menu.ShellItem("Sleep", "systemctl suspend"),
        rofi_menu.NestedMenu("Logout", LogoutMenu()),
    ]


if __name__ == "__main__":
    rofi_menu.run(MainMenu(), rofi_version="1.6")  # change to 1.5 if you use older rofi version

Run it as:

$ rofi -modi mymenu:/path/to/example.py -show mymenu -show-icons

It'll result in

rofi menu

Advanced example

#!/home/user/pyenv/versions/rofi/bin/python
import asyncio
from datetime import datetime
import os

import rofi_menu


class OutputSomeTextItem(rofi_menu.Item):
    """Output arbitrary text on selection"""
    async def on_select(self, meta):
        # any python code
        await asyncio.sleep(0.1)
        return rofi_menu.Operation(rofi_menu.OP_OUTPUT, (
            "💢 simple\n"
            "💥 multi-\n"
            "💫 <b>line</b>\n"
            "💣 <i>text</i>\n"
        ))


class DoAndExitItem(rofi_menu.Item):
    """Do something and exit"""
    async def on_select(self, meta):
        os.system('notify-send msg')
        return rofi_menu.Operation(rofi_menu.OP_EXIT)


class CurrentDatetimeItem(rofi_menu.Item):
    """Show current datetime inside menu item"""
    async def load(self, meta):
        self.state = datetime.now().strftime('%A %d. %B %Y (%H:%M:%S)')

    async def render(self, meta):
        return f"🕑 {self.state}"


class CounterItem(rofi_menu.Item):
    """Increment counter on selection"""
    async def load(self, meta):
        await super().load(meta)
        self.state = self.state or 0
        meta.session.setdefault("counter_total", 0)

    async def on_select(self, meta):
        self.state += 1
        meta.session["counter_total"] += 1
        return await super().on_select(meta)

    async def render(self, meta):
        per_menu_item = self.state
        total = meta.session["counter_total"]
        return f"🏃 Selected #{per_menu_item} time(s) (across menu items #{total})"


class HandleUserInputMenu(rofi_menu.Menu):
    allow_user_input = True

    class CustomItem(rofi_menu.Item):
        async def render(self, meta):
            entered_text = meta.session.get("text", "[ no text ]")
            return f"You entered: {entered_text}"

    items = [CustomItem()]

    async def on_user_input(self, meta):
        meta.session['text'] = meta.user_input
        return rofi_menu.Operation(rofi_menu.OP_REFRESH_MENU)


main_menu = rofi_menu.Menu(
    prompt="menu",
    items=[
        OutputSomeTextItem("Output anything"),
        DoAndExitItem("Do something and exit"),
        CurrentDatetimeItem(),
        CounterItem(),
        CounterItem(),
        rofi_menu.NestedMenu("User input", HandleUserInputMenu()),
    ],
)


if __name__ == "__main__":
    rofi_menu.run(main_menu)

advanced example

TODO

  • documentation of API
  • examples
  • tests

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rofi-menu-0.6.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

rofi_menu-0.6-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file rofi-menu-0.6.tar.gz.

File metadata

  • Download URL: rofi-menu-0.6.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.10 CPython/3.8.5 Linux/5.8.0-50-generic

File hashes

Hashes for rofi-menu-0.6.tar.gz
Algorithm Hash digest
SHA256 96df3ef2fe622ab65675548b9f4e11e82052c039fbc0a26e4787db59921695be
MD5 d06e98d81cc9e6498c9a60df39de3836
BLAKE2b-256 874f6ca17850ded7e2cc019ac9fe14b9bc24b874b936ec23cc1aacadb0e4423d

See more details on using hashes here.

File details

Details for the file rofi_menu-0.6-py3-none-any.whl.

File metadata

  • Download URL: rofi_menu-0.6-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.10 CPython/3.8.5 Linux/5.8.0-50-generic

File hashes

Hashes for rofi_menu-0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 ae9791f6332448876c499a0b011da6c7df595c360110c0557a2b98ef8eb3e412
MD5 2ef92ec665ba13ac6eeaccfb368a4204
BLAKE2b-256 2248d59deea04e60c6ec6b910a4329fc2b30be4085405b86b2b5c3bd7a258664

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page