qutebrowser profile manager
at 0.2 119 lines 4.1 kB view raw
1from pathlib import Path 2from textwrap import dedent 3from typing import List, Optional 4 5from xdg import BaseDirectory # type: ignore 6from xdg.DesktopEntry import DesktopEntry # type: ignore 7 8from qpm.utils import error, user_config_dir 9 10 11class Profile: 12 name: str 13 profile_dir: Path 14 set_app_id: bool 15 root: Path 16 17 def __init__( 18 self, name: str, profile_dir: Optional[Path], set_app_id: bool = False 19 ) -> None: 20 self.name = name 21 self.profile_dir = profile_dir or Path( 22 BaseDirectory.save_data_path("qutebrowser-profiles") 23 ) 24 self.set_app_id = set_app_id 25 self.root = self.profile_dir / name 26 27 def check(self) -> Optional["Profile"]: 28 if "/" in self.name: 29 error("profile name cannot contain slashes") 30 return None 31 if not self.profile_dir.resolve().is_dir(): 32 error(f"{self.profile_dir} is not a directory") 33 return None 34 if self.profile_dir.resolve() not in self.root.resolve().parents: 35 error("will not create profile outside of profile dir. consider using -P") 36 return None 37 if self.root.exists(): 38 error(f"{self.root} already exists") 39 return None 40 for parent in self.root.parents: 41 if parent == self.profile_dir: 42 break 43 if parent.exists(): 44 error(f"{parent} already exists") 45 return None 46 return self 47 48 def exists(self) -> bool: 49 return self.root.exists() and self.root.is_dir() 50 51 def cmdline(self) -> List[str]: 52 return ["qutebrowser", "-B", str(self.root), "--qt-arg", "name", self.name] + ( 53 ["--desktop-file-name", self.name] if self.set_app_id else [] 54 ) 55 56 57def create_profile(profile: Profile) -> bool: 58 if not profile.check(): 59 return False 60 61 config_dir = profile.root / "config" 62 config_dir.mkdir(parents=True) 63 print(profile.root) 64 return True 65 66 67def create_config(profile: Profile, home_page: Optional[str] = None) -> None: 68 user_config = profile.root / "config" / "config.py" 69 with user_config.open(mode="x") as dest_config: 70 title_prefix = "{perc}{current_title}{title_sep}" 71 config = ( 72 f"c.window.title_format = '{title_prefix} qutebrowser ({profile.name})'" 73 ) 74 if home_page: 75 config = config + f"\nc.url.default_page = '{home_page}'" 76 config = config + f"\nc.url.start_pages = ['{home_page}']" 77 main_config_dir = user_config_dir() 78 print(dedent(config), file=dest_config) 79 print(f"config.source('{main_config_dir / 'config.py'}')", file=dest_config) 80 for conf in main_config_dir.glob("conf.d/*.py"): 81 print(f"config.source('{conf}')", file=dest_config) 82 83 84application_dir = Path(BaseDirectory.xdg_data_home) / "applications" / "qpm" 85 86 87def create_desktop_file(profile: Profile): 88 desktop = DesktopEntry(str(application_dir / f"{profile.name}.desktop")) 89 desktop.set("Name", f"{profile.name} (qutebrowser profile)") 90 # TODO allow passing in an icon value 91 desktop.set("Icon", "qutebrowser") 92 desktop.set("Exec", " ".join(profile.cmdline()) + " %u") 93 desktop.set("Categories", ["Network"]) 94 desktop.set("Terminal", False) 95 desktop.set("StartupNotify", True) 96 desktop.write() 97 98 99def ensure_profile_exists(profile: Profile, create: bool = True) -> bool: 100 if profile.root.exists() and not profile.root.is_dir(): 101 error(f"{profile.root} is not a directory") 102 return False 103 if not profile.root.exists() and create: 104 return new_profile(profile) 105 if not profile.root.exists(): 106 error(f"{profile.root} does not exist") 107 return False 108 return True 109 110 111def new_profile( 112 profile: Profile, home_page: Optional[str] = None, desktop_file: bool = True 113) -> bool: 114 if create_profile(profile): 115 create_config(profile, home_page) 116 if desktop_file: 117 create_desktop_file(profile) 118 return True 119 return False