Coverage for src/pyselector/menus/fzf.py: 100%

55 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-29 12:33 -0300

1# fzf.py 

2from __future__ import annotations 

3 

4import logging 

5import shlex 

6from typing import Iterable 

7from typing import Optional 

8from typing import Union 

9 

10from pyselector import helpers 

11from pyselector.key_manager import KeyManager 

12 

13log = logging.getLogger(__name__) 

14 

15 

16class Fzf: 

17 def __init__(self) -> None: 

18 self.name = "fzf" 

19 self.url = "https://github.com/junegunn/fzf" 

20 self.keybind = KeyManager() 

21 

22 @property 

23 def command(self) -> str: 

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

25 

26 def _build_command( 

27 self, 

28 case_sensitive, 

29 multi_select, 

30 prompt, 

31 **kwargs, 

32 ) -> list[str]: 

33 header: list[str] = [] 

34 args = shlex.split(self.command) 

35 

36 if case_sensitive is not None: 

37 args.append("+i" if case_sensitive else "-i") 

38 

39 if kwargs.get("mesg"): 

40 header.extend(shlex.split(f"'{kwargs.pop('mesg')}'")) 

41 

42 if kwargs.get("cycle"): 

43 kwargs.pop("cycle") 

44 args.append("--cycle") 

45 

46 if not kwargs.pop("preview", None): 

47 args.append("--no-preview") 

48 

49 if kwargs.get("height"): 

50 args.extend(shlex.split(f"--height {kwargs.pop('height')}")) 

51 

52 if prompt: 

53 args.extend(["--prompt", prompt]) 

54 

55 if multi_select: 

56 args.append("--multi") 

57 

58 # FIX: rethink keybinds for FZF 

59 log.debug("keybinds are disabled") 

60 for key in self.keybind.all_registered: 

61 args.extend(shlex.split(f"--bind='{key.bind}:{key.action}'")) 

62 if not key.hidden: 

63 header.append(f"Use {key.bind} {key.description}") 

64 

65 if kwargs: 

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

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

68 

69 if header: 

70 mesg = "\n".join(msg.replace("\n", " ") for msg in header) 

71 args.extend(shlex.split(f"--header '{mesg}'")) 

72 

73 return args 

74 

75 def prompt( 

76 self, 

77 items: Optional[Iterable[Union[str, int]]] = None, 

78 case_sensitive: bool = None, 

79 multi_select: bool = False, 

80 prompt: str = "PySelector> ", 

81 **kwargs, 

82 ) -> tuple[Union[str, list[str]], int]: 

83 if not items: 

84 items = [] 

85 

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

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

88 

89 if multi_select: 

90 return helpers.parse_multiple_bytes_lines(selection), code 

91 return helpers.parse_bytes_line(selection), code