~pvsr/qpm

qpm/qpm/operations.py -rw-r--r-- 4.7 KiB
8b6b26a0Peter Rice document dmenu-wl support 2 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
142
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 SUPPORTED_MENUS, 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:
        args.menu = "dmenu" if args.dmenu else get_default_menu()
        if not args.menu:
            error("No suitable menu program found, please install rofi or dmenu")
            return None
    elif args.menu not in SUPPORTED_MENUS:
        error(
            f"'{args.menu}' is not a valid menu program, please specify one of: {SUPPORTED_MENUS}"
        )
        return None
    elif args.menu == "applescript" and platform != "darwin":
        error(f"Menu applescript cannot be used on a {platform} host")
        return None
    elif args.dmenu:
        args.menu = "dmenu"
    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 in ["dmenu", "dmenu-wl"]:
        dmenu_command = args.dmenu or f"{args.menu} -p qutebrowser"
        cmd_string = f'echo "{profile_list}" | {dmenu_command}'
    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"))