diff --git a/fastanime/cli/interfaces/anilist_interfaces.py b/fastanime/cli/interfaces/anilist_interfaces.py index d22cbe1..4ac8ad9 100644 --- a/fastanime/cli/interfaces/anilist_interfaces.py +++ b/fastanime/cli/interfaces/anilist_interfaces.py @@ -764,18 +764,22 @@ def provider_anime_episodes_menu( if not current_episode_number or current_episode_number not in available_episodes: choices = [*available_episodes, "Back"] preview = None - if config.preview: - from .utils import get_fzf_episode_preview - - e = fastanime_runtime_state.selected_anime_anilist["episodes"] - if e: - eps = range(0, e + 1) - else: - eps = available_episodes - preview = get_fzf_episode_preview( - fastanime_runtime_state.selected_anime_anilist, eps - ) if config.use_fzf: + if config.preview: + from .utils import get_fzf_episode_preview + + e = fastanime_runtime_state.selected_anime_anilist["episodes"] + if e: + eps = range(0, e + 1) + else: + eps = available_episodes + preview = get_fzf_episode_preview( + fastanime_runtime_state.selected_anime_anilist, eps + ) + + if not preview: + print("Failed to find bash executable which is necessary for preview with fzf.\nIf you are on Windows, please make sure Git is installed and available in PATH.") + current_episode_number = fzf.run( choices, prompt="Select Episode", header=anime_title, preview=preview ) @@ -1498,6 +1502,9 @@ def anilist_results_menu( from .utils import get_fzf_anime_preview preview = get_fzf_anime_preview(search_results, anime_data.keys()) + if not preview: + print("Failed to find bash executable which is necessary for preview with fzf.\nIf you are on Windows, please make sure Git is installed and available in PATH.") + selected_anime_title = fzf.run( choices, prompt="Select Anime", diff --git a/fastanime/cli/interfaces/utils.py b/fastanime/cli/interfaces/utils.py index 7b23430..e86d414 100644 --- a/fastanime/cli/interfaces/utils.py +++ b/fastanime/cli/interfaces/utils.py @@ -13,7 +13,7 @@ from ...constants import APP_CACHE_DIR, S_PLATFORM from ...libs.anilist.types import AnilistBaseMediaDataSchema from ...Utility import anilist_data_helper from ..utils.scripts import fzf_preview -from ..utils.utils import get_true_fg +from ..utils.utils import get_true_fg, which_bashlike logger = logging.getLogger(__name__) @@ -279,6 +279,9 @@ def get_fzf_episode_preview( titles (list[str]): sanitized titles of the anime; NOTE: its important that they are sanitized since they are used as the filenames of the images workers ([TODO:parameter]): Number of threads to use to download the images; defaults to as many as possible anilist_results: the anilist results from an anilist action + + Returns: + The fzf preview script to use or None if the bash is not found """ # HEADER_COLOR = 215, 0, 95 @@ -345,7 +348,11 @@ def get_fzf_episode_preview( background_worker.start() # the preview script is in bash so making sure fzf doesnt use any other shell lang to process the preview script - os.environ["SHELL"] = shutil.which("bash") or "bash" + bash_path = which_bashlike() + if not bash_path: + return + + os.environ["SHELL"] = bash_path if S_PLATFORM == "win32": preview = """ %s @@ -412,7 +419,7 @@ def get_fzf_anime_preview( anilist_results: the anilist results got from an anilist action Returns: - THe fzf preview script to use + The fzf preview script to use or None if the bash is not found """ # ensure images and info exists @@ -423,7 +430,12 @@ def get_fzf_anime_preview( background_worker.start() # the preview script is in bash so making sure fzf doesnt use any other shell lang to process the preview script - os.environ["SHELL"] = shutil.which("bash") or "bash" + bash_path = which_bashlike() + if not bash_path: + return + + os.environ["SHELL"] = bash_path + if S_PLATFORM == "win32": preview = """ %s diff --git a/fastanime/cli/utils/utils.py b/fastanime/cli/utils/utils.py index 1e96c8f..89aa22b 100644 --- a/fastanime/cli/utils/utils.py +++ b/fastanime/cli/utils/utils.py @@ -1,8 +1,11 @@ import logging +import shutil from typing import TYPE_CHECKING from InquirerPy import inquirer +from fastanime.constants import S_PLATFORM + logger = logging.getLogger(__name__) if TYPE_CHECKING: from ...libs.anime_provider.types import EpisodeStream @@ -155,3 +158,38 @@ def fuzzy_inquirer(choices: list, prompt: str, **kwargs): **kwargs, ).execute() return action + + +def which_win32_gitbash(): + """Helper function that returns absolute path to the git bash executable + (came with Git for Windows) on Windows + + Returns: + the path to the git bash executable or None if not found + """ + from os import path + + gb_path = shutil.which("bash") + + # Windows came with its own bash.exe but it's just an entry point for WSL not Git Bash + if gb_path and not path.dirname(gb_path).lower().endswith("windows\\system32"): + return gb_path + + git_path = shutil.which("git") + + if git_path and path.dirname(git_path).endswith("cmd"): + gb_path = path.abspath( + path.join(path.dirname(git_path), "..", "bin", "bash.exe") + ) + + if path.exists(gb_path): + return gb_path + + +def which_bashlike(): + """Helper function that returns absolute path to the bash executable for the current platform + + Returns: + the path to the bash executable or None if not found + """ + return (shutil.which("bash") or "bash") if S_PLATFORM != "win32" else which_win32_gitbash() \ No newline at end of file