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

54 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-24 11:53 -0300

1# fzf.py 

2 

3import logging 

4import shlex 

5import warnings 

6from typing import Iterable 

7from typing import Optional 

8from typing import Union 

9 

10from pyselector import helpers 

11from pyselector.interfaces 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 kwargs.get("preview") is not None: 

47 preview = kwargs.pop("preview") 

48 if not preview: 

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

50 

51 if prompt: 

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

53 

54 if multi_select: 

55 args.append("--multi") 

56 

57 for key in self.keybind.list_registered: 

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

59 if not key.hidden: 

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

61 

62 if kwargs: 

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

64 warnings.warn(UserWarning(f"'{arg}={value}' not supported")) 

65 

66 if header: 

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

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

69 

70 return args 

71 

72 def prompt( 

73 self, 

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

75 case_sensitive: bool = None, 

76 multi_select: bool = False, 

77 prompt: str = "PySelector> ", 

78 **kwargs, 

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

80 if not items: 

81 items = [] 

82 

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

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

85 

86 if multi_select: 

87 return helpers.parse_multiple_bytes_lines(selection), code 

88 return helpers.parse_bytes_line(selection), code