~pvsr/qbpm

ref: bab6b19153e9cf288ec0dd26240f31e381afb492 qbpm/qpm/operations.py -rw-r--r-- 4.6 KiB
bab6b191Peter Rice nix flake dev shell 10 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import argparse
import os
import shutil
import subprocess
from pathlib import Path
from sys import platform
from typing import List, Optional

from xdg import BaseDirectory  # type: ignore
from xdg.DesktopEntry import DesktopEntry  # type: ignore

from qpm import profiles
from qpm.profiles import Profile
from qpm.utils import error, get_default_menu, user_data_dir


def from_session(
    session: str,
    profile_name: Optional[str] = None,
    profile_dir: Optional[Path] = None,
    desktop_file: bool = True,
    overwrite: bool = False,
) -> Optional[Profile]:
    if session.endswith(".yml"):
        session_file = Path(session).expanduser()
        session_name = session_file.stem
    else:
        session_name = session
        session_file = user_data_dir() / "sessions" / (session_name + ".yml")
    if not session_file.is_file():
        error(f"{session_file} is not a file")
        return None

    profile = Profile(profile_name or session_name, profile_dir)
    if not profiles.new_profile(profile, None, desktop_file, overwrite):
        return None

    session_dir = profile.root / "data" / "sessions"
    session_dir.mkdir(parents=True, exist_ok=overwrite)
    shutil.copy(session_file, session_dir / "_autosave.yml")

    return profile


def launch(
    profile: Profile, strict: bool, foreground: bool, qb_args: List[str]
) -> bool:
    if not profiles.ensure_profile_exists(profile, not strict):
        return False

    args = profile.cmdline() + qb_args
    if foreground:
        os.execlp("qutebrowser", *args)
    else:
        p = subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
        try:
            # give qb a chance to validate input before returning to shell
            stdout, stderr = p.communicate(timeout=0.1)
            print(stderr.decode(errors="ignore"), end="")
        except subprocess.TimeoutExpired:
            pass

    return True


application_dir = Path(BaseDirectory.xdg_data_home) / "applications" / "qbpm"


def desktop(profile: Profile):
    if profile.exists():
        profiles.create_desktop_file(profile)
    else:
        error(f"profile {profile.name} not found at {profile.root}")


def list_(args: argparse.Namespace) -> None:
    for profile in sorted(args.profile_dir.iterdir()):
        print(profile.name)


def choose(args: argparse.Namespace) -> None:
    if not args.menu:
        default_menu = get_default_menu()
        if default_menu:
            args.menu = default_menu
        else:
            error("No suitable menu program found, please install rofi or dmenu")
            return None
    elif args.menu not in ["rofi", "dmenu", "applescript"]:
        error(
            f"{args.menu} is not a valid menu program, please specify one of rofi, dmenu, or applescript"
        )
        return None
    elif args.menu == "applescript" and platform != "darwin":
        error(f"Menu applescript cannot be used on a {platform} host")
        return None
    elif shutil.which(args.menu) is None:
        error(f"{args.menu} not found on path")
        return None

    profile_list = "\n".join(
        [profile.name for profile in sorted(args.profile_dir.iterdir())]
    )
    if not profile_list:
        error("No existing profiles found, create a profile first with qbpm new")
        return None

    if args.menu == "rofi":
        arg_string = " ".join(args.qb_args)
        cmd_string = f'echo "{profile_list}" | rofi -dmenu -no-custom -p qutebrowser -mesg {arg_string}'
    elif args.menu == "dmenu":
        cmd_string = f'echo "{profile_list}" | dmenu -p qutebrowser'
    elif args.menu == "applescript":
        profile_list = '", "'.join(profile_list.split("\n"))
        arg_string = " ".join(args.qb_args)
        cmd_string = f"""osascript -e \'set profiles to {{"{profile_list}"}}
set profile to choose from list profiles with prompt "qutebrowser: {arg_string}" default items {{item 1 of profiles}}
item 1 of profile\'"""

    selection_cmd = subprocess.Popen(
        cmd_string, shell=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL
    )
    out = selection_cmd.stdout
    if not out:
        error(f"Could not read {args.menu} stdout")
        return None
    selection = out.read().decode(errors="ignore").rstrip("\n")

    if selection:
        profile = Profile(selection, args.profile_dir, args.set_app_id)
        launch(profile, True, args.foreground, args.qb_args)
    else:
        error("No profile selected")


def edit(profile: Profile):
    if not profile.exists():
        error(f"profile {profile.name} not found at {profile.root}")
        return
    editor = os.environ.get("VISUAL") or os.environ.get("EDITOR") or "vim"
    os.execlp(editor, editor, str(profile.root / "config" / "config.py"))