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