Coverage for src/pyselector/menus/dmenu.py: 93%
43 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-29 12:33 -0300
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-29 12:33 -0300
1# dmenu.py
2from __future__ import annotations
4import logging
5import shlex
6from typing import TYPE_CHECKING
7from typing import Iterable
8from typing import Optional
9from typing import Union
11from pyselector import helpers
12from pyselector.key_manager import KeyManager
14if TYPE_CHECKING:
15 from pyselector.interfaces import PromptReturn
17log = logging.getLogger(__name__)
20class Dmenu:
21 def __init__(self) -> None:
22 self.name = "dmenu"
23 self.url = "https://tools.suckless.org/dmenu/"
24 self.keybind = KeyManager()
26 @property
27 def command(self) -> str:
28 return helpers.check_command(self.name, self.url)
30 def _build_command(
31 self,
32 case_sensitive,
33 multi_select,
34 prompt,
35 **kwargs,
36 ) -> list[str]:
37 args = shlex.split(self.command)
39 if kwargs.get("lines"):
40 args.extend(["-l", str(kwargs.pop("lines"))])
42 if prompt:
43 args.extend(["-p", prompt])
45 if kwargs.get("bottom"):
46 kwargs.pop("bottom")
47 args.append("-b")
49 if case_sensitive:
50 args.append("-i")
52 if kwargs.get("font"):
53 args.extend(["-fn", kwargs.pop("font")])
55 if multi_select:
56 log.warning("not supported in dmenu: %s", "multi-select")
58 if kwargs:
59 for arg, value in kwargs.items():
60 log.debug("'%s=%s' not supported", arg, value)
61 return args
63 def prompt(
64 self,
65 items: Optional[Iterable[Union[str, int]]] = None,
66 case_sensitive: bool = False,
67 multi_select: bool = False,
68 prompt: str = "PySelector> ",
69 **kwargs,
70 ) -> PromptReturn:
71 """Prompts the user with a rofi window containing the given items
72 and returns the selected item and code.
74 Args:
75 items (Iterable[str, int], optional): The items to display in the rofi window
76 case_sensitive (bool, optional): Whether or not to perform a case-sensitive search
77 multi_select (bool, optional): Whether or not to allow the user to select multiple items
78 prompt (str, optional): The prompt to display in the rofi window
79 **kwargs: Additional keyword arguments.
81 Keyword Args:
82 lines (int): dmenu lists items vertically, with the given number of lines.
83 bottom (str): dmenu appears at the bottom of the screen.
84 font (str): defines the font or font set used.
85 height (str): The height of the selection window (e.g. 50%).
87 Returns:
88 A tuple containing the selected item (str or list of str) and the return code (int).
89 """
90 if items is None:
91 items = []
93 args = self._build_command(case_sensitive, multi_select, prompt, **kwargs)
95 selection, code = helpers._execute(args, items)
96 return helpers.parse_bytes_line(selection), code