Created
August 11, 2022 09:43
-
-
Save altescy/f526874b3de783093b11e8cab971e70b to your computer and use it in GitHub Desktop.
Example of interactive selector in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
import os | |
import shutil | |
import subprocess | |
class Selector: | |
SUPPORTED_SELECTOR_COMMANDS = {"fzf", "peco"} | |
ENVKEY_SELECTOR_COMMAND = "SELECTOR_COMMAND" | |
def __init__( | |
self, | |
selector_command: str | None = None, | |
) -> None: | |
self._selector_command = selector_command or self._find_selector_command() | |
def __call__(self, items: list[str]) -> str: | |
if self._selector_command: | |
return self._select_with_command(items) | |
return self._select_without_command(items) | |
def _format_list(self, items: list[str]) -> str: | |
return "\n".join(f"{i}: {item}" for i, item in enumerate(items, start=1)) | |
def _parse_result(self, line: str) -> str: | |
return line.strip().split(": ", 1)[-1] | |
def _select_without_command(self, items: list[str]) -> str: | |
print(self._format_list(items)) | |
index = int(input("select index > ")) - 1 | |
return items[index] | |
def _select_with_command(self, items: list[str]) -> str: | |
assert self._selector_command is not None | |
proc = subprocess.Popen( | |
[self._selector_command], | |
stdin=subprocess.PIPE, | |
stdout=subprocess.PIPE, | |
stderr=None, | |
) | |
stdin = proc.stdin | |
stdout = proc.stdout | |
assert stdin is not None | |
assert stdout is not None | |
stdin.write(self._format_list(items).encode()) | |
stdin.flush() | |
stdin.close() | |
proc.wait() | |
return self._parse_result(stdout.read().decode()) | |
def _find_selector_command(self) -> str | None: | |
cmd = os.environ.get(self.ENVKEY_SELECTOR_COMMAND) | |
if cmd: | |
return cmd | |
for cmd in self.SUPPORTED_SELECTOR_COMMANDS: | |
if shutil.which(cmd): | |
return cmd | |
return None | |
if __name__ == "__main__": | |
selector = Selector("fzf") | |
result = selector(["foo", "bar", "baz"]) | |
print(f"{result} was selected.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment