mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-26 12:51:15 -08:00
153 lines
3.9 KiB
Python
153 lines
3.9 KiB
Python
import logging
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from typing import Callable, List
|
|
|
|
from art import text2art
|
|
from rich import print
|
|
|
|
from ...constants import PLATFORM
|
|
from .config import FZF_DEFAULT_OPTS, FzfOptions
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# fzf\
|
|
# --info=hidden \
|
|
# --layout=reverse \
|
|
# --height=100% \
|
|
# --prompt="Select Channel: " \
|
|
# --header="$fzf_header" \
|
|
# --preview-window=left,50%\
|
|
# --bind=right:accept \
|
|
# --expect=shift-left,shift-right\
|
|
# --tabstop=1 \
|
|
# --no-margin \
|
|
# +m \
|
|
# -i \
|
|
# --exact \
|
|
|
|
|
|
def clear():
|
|
if PLATFORM == "Windows":
|
|
os.system("cls")
|
|
else:
|
|
os.system("clear")
|
|
|
|
|
|
class FZF:
|
|
if not os.getenv("FZF_DEFAULT_OPTS"):
|
|
os.environ["FZF_DEFAULT_OPTS"] = FZF_DEFAULT_OPTS
|
|
FZF_EXECUTABLE = shutil.which("fzf")
|
|
default_options = [
|
|
"--cycle",
|
|
"--info=hidden",
|
|
"--layout=reverse",
|
|
"--height=100%",
|
|
"--bind=right:accept",
|
|
"--no-margin",
|
|
"+m",
|
|
"-i",
|
|
"--exact",
|
|
"--tabstop=1",
|
|
"--preview-window=left,35%,wrap",
|
|
"--wrap",
|
|
]
|
|
|
|
def _with_filter(self, command: str, work: Callable) -> List[str]:
|
|
try:
|
|
process = subprocess.Popen(
|
|
command,
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
text=True,
|
|
shell=True,
|
|
)
|
|
except subprocess.SubprocessError as e:
|
|
print(f"Failed to start subprocess: {e}", file=sys.stderr)
|
|
return []
|
|
|
|
original_stdout = sys.stdout
|
|
sys.stdout = process.stdin
|
|
|
|
try:
|
|
work()
|
|
if process.stdin:
|
|
process.stdin.close()
|
|
except Exception as e:
|
|
print(f"Exception during work execution: {e}", file=sys.stderr)
|
|
finally:
|
|
sys.stdout = original_stdout
|
|
|
|
output = []
|
|
if process.stdout:
|
|
output = process.stdout.read().splitlines()
|
|
process.stdout.close()
|
|
|
|
return output
|
|
|
|
def _run_fzf(self, commands: list[FzfOptions], _fzf_input) -> str:
|
|
fzf_input = "\n".join(_fzf_input)
|
|
|
|
if not self.FZF_EXECUTABLE:
|
|
raise Exception("fzf executable not found")
|
|
|
|
result = subprocess.run(
|
|
[self.FZF_EXECUTABLE, *commands],
|
|
input=fzf_input,
|
|
stdout=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
if not result or result.returncode != 0 or not result.stdout:
|
|
print("sth went wrong:confused:")
|
|
input("press enter to try again...")
|
|
clear()
|
|
return self._run_fzf(commands, _fzf_input)
|
|
clear()
|
|
|
|
return result.stdout.strip()
|
|
|
|
def run(
|
|
self,
|
|
fzf_input: list[str],
|
|
prompt: str,
|
|
header: str,
|
|
preview: str | None = None,
|
|
expect: str | None = None,
|
|
validator: Callable | None = None,
|
|
) -> str:
|
|
_commands = [
|
|
*self.default_options,
|
|
"--header",
|
|
text2art(header),
|
|
"--header-first",
|
|
"--prompt",
|
|
prompt.title(),
|
|
] # pyright:ignore
|
|
|
|
if preview:
|
|
_commands.append(f"--preview={preview}")
|
|
if expect:
|
|
_commands.append(f"--expect={expect}")
|
|
|
|
result = self._run_fzf(_commands, fzf_input) # pyright:ignore
|
|
if not result:
|
|
print("Please enter a value")
|
|
input("Enter to do it right")
|
|
return self.run(fzf_input, prompt, header, preview, expect, validator)
|
|
elif validator:
|
|
success, info = validator(result)
|
|
if not success:
|
|
print(info)
|
|
input("Enter to try again")
|
|
return self.run(fzf_input, prompt, header, preview, expect, validator)
|
|
return result
|
|
|
|
|
|
fzf = FZF()
|
|
|
|
if __name__ == "__main__":
|
|
fzf.run([*os.listdir(), "exit"], "Prompt: ", "Header", preview="bat {}")
|