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

1# dmenu.py 

2from __future__ import annotations 

3 

4import logging 

5import shlex 

6from typing import TYPE_CHECKING 

7from typing import Iterable 

8from typing import Optional 

9from typing import Union 

10 

11from pyselector import helpers 

12from pyselector.key_manager import KeyManager 

13 

14if TYPE_CHECKING: 

15 from pyselector.interfaces import PromptReturn 

16 

17log = logging.getLogger(__name__) 

18 

19 

20class Dmenu: 

21 def __init__(self) -> None: 

22 self.name = "dmenu" 

23 self.url = "https://tools.suckless.org/dmenu/" 

24 self.keybind = KeyManager() 

25 

26 @property 

27 def command(self) -> str: 

28 return helpers.check_command(self.name, self.url) 

29 

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) 

38 

39 if kwargs.get("lines"): 

40 args.extend(["-l", str(kwargs.pop("lines"))]) 

41 

42 if prompt: 

43 args.extend(["-p", prompt]) 

44 

45 if kwargs.get("bottom"): 

46 kwargs.pop("bottom") 

47 args.append("-b") 

48 

49 if case_sensitive: 

50 args.append("-i") 

51 

52 if kwargs.get("font"): 

53 args.extend(["-fn", kwargs.pop("font")]) 

54 

55 if multi_select: 

56 log.warning("not supported in dmenu: %s", "multi-select") 

57 

58 if kwargs: 

59 for arg, value in kwargs.items(): 

60 log.debug("'%s=%s' not supported", arg, value) 

61 return args 

62 

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. 

73 

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. 

80 

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%). 

86 

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 = [] 

92 

93 args = self._build_command(case_sensitive, multi_select, prompt, **kwargs) 

94 

95 selection, code = helpers._execute(args, items) 

96 return helpers.parse_bytes_line(selection), code