feat: qutebrowser profiles (inspired by qbpm)
This commit is contained in:
@@ -195,6 +195,7 @@
|
||||
};
|
||||
neovim = inputs.neovim.homeManagerModules.default;
|
||||
eww = ./modules/home-manager/eww.nix;
|
||||
qutebrowser-profiles = ./modules/home-manager/qutebrowser-profiles.nix;
|
||||
};
|
||||
|
||||
packages = forAllSystems ({
|
||||
@@ -208,7 +209,7 @@
|
||||
neovim = inputs.neovim.packages.${pkgs.system}.default;
|
||||
|
||||
devkit =
|
||||
(import ./packages/devkit {inherit pkgs inputs;})
|
||||
(import ./packages/devkit {inherit inputs pkgs;})
|
||||
// {
|
||||
neovim = self.packages.${pkgs.system}.neovim;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
self.homeManagerModules.qutebrowser-profiles
|
||||
];
|
||||
|
||||
programs.qutebrowser.enable = true;
|
||||
programs.qutebrowser.settings = {
|
||||
auto_save.session = true;
|
||||
@@ -88,4 +92,19 @@
|
||||
];
|
||||
})
|
||||
];
|
||||
programs.qutebrowser.profiles = {
|
||||
"art" = {};
|
||||
"personal" = {};
|
||||
"work" = {
|
||||
searchEngines = {
|
||||
# Languages
|
||||
go = "https://pkg.go.dev/search?q={}";
|
||||
};
|
||||
};
|
||||
"job" = {
|
||||
settings.confirm_quit = ["always"];
|
||||
};
|
||||
"shopping" = {};
|
||||
"goverment" = {};
|
||||
};
|
||||
}
|
||||
|
||||
302
modules/home-manager/qutebrowser-profiles.nix
Normal file
302
modules/home-manager/qutebrowser-profiles.nix
Normal file
@@ -0,0 +1,302 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
concatStringsSep
|
||||
literalExpression
|
||||
mapAttrsToList
|
||||
mkIf
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.programs.qutebrowser;
|
||||
|
||||
profileType = with lib;
|
||||
with types;
|
||||
submodule ({
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
scfg = config;
|
||||
in {
|
||||
options = with lib; {
|
||||
name = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
extendDefault = mkOption {
|
||||
type = with types; bool;
|
||||
default = true;
|
||||
};
|
||||
titleFormat = mkOption {
|
||||
type = with types; str;
|
||||
default = "{perc}{current_title}{title_sep} qutebrowser ({profile_name})";
|
||||
};
|
||||
desktopName = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
aliases = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
};
|
||||
loadAutoconfig = mkOption {
|
||||
type = with types; bool;
|
||||
default = cfg.loadAutoconfig;
|
||||
};
|
||||
searchEngines = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
};
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf anything;
|
||||
default = {};
|
||||
};
|
||||
keyMappings = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
};
|
||||
enableDefaultBindings = mkOption {
|
||||
type = with types; bool;
|
||||
default = cfg.enableDefaultBindings;
|
||||
};
|
||||
keyBindings = mkOption {
|
||||
type = with types; attrsOf (attrsOf (nullOr (separatedString " ;; ")));
|
||||
default = {};
|
||||
};
|
||||
quickmarks = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
apply = v:
|
||||
if scfg.extendDefault
|
||||
then cfg.quickmarks // v
|
||||
else v;
|
||||
};
|
||||
greasemonkey = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = [];
|
||||
apply = v:
|
||||
if scfg.extendDefault
|
||||
then cfg.greasemonkey ++ v
|
||||
else v;
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = with types; lines;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
formatLine = o: n: v: let
|
||||
formatValue = v:
|
||||
if v == null
|
||||
then "None"
|
||||
else if builtins.isBool v
|
||||
then
|
||||
(
|
||||
if v
|
||||
then "True"
|
||||
else "False"
|
||||
)
|
||||
else if builtins.isString v
|
||||
then ''"${v}"''
|
||||
else if builtins.isList v
|
||||
then "[${concatStringsSep ", " (map formatValue v)}]"
|
||||
else builtins.toString v;
|
||||
in
|
||||
if builtins.isAttrs v
|
||||
then concatStringsSep "\n" (mapAttrsToList (formatLine "${o}${n}.") v)
|
||||
else "${o}${n} = ${formatValue v}";
|
||||
|
||||
formatDictLine = o: n: v: ''${o}['${n}'] = "${v}"'';
|
||||
|
||||
formatKeyBindings = m: b: let
|
||||
formatKeyBinding = m: k: c:
|
||||
if c == null
|
||||
then ''config.unbind("${k}", mode="${m}")''
|
||||
else ''config.bind("${k}", "${lib.escape [''"''] c}", mode="${m}")'';
|
||||
in
|
||||
concatStringsSep "\n" (mapAttrsToList (formatKeyBinding m) b);
|
||||
|
||||
formatQuickmarks = n: s: "${n} ${s}";
|
||||
in
|
||||
with lib; {
|
||||
options.programs.qutebrowser = {
|
||||
profileChooser = mkOption {
|
||||
type = with types; either bool (enum ["override"]);
|
||||
default = "override";
|
||||
};
|
||||
profileChooserDMenu = mkOption {
|
||||
type = with types; package;
|
||||
default = pkgs.writeShellScriptBin "rofi" "${getExe config.programs.rofi.finalPackage} -dmenu $@";
|
||||
};
|
||||
profileChooserUserscript = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "W";
|
||||
};
|
||||
profiles = mkOption {
|
||||
type = with types; attrsOf profileType;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
config = let
|
||||
profiles = mapAttrsToList (n: v: n) cfg.profiles;
|
||||
profilesFile = pkgs.writeText "qutebrowser-profiles" (concatStringsSep "\n" (["DEFAULT"] ++ profiles));
|
||||
|
||||
chooser = pkgs.writeShellScriptBin "qutebrowser-chooser" ''
|
||||
profile="$(cat ${profilesFile} | ${getExe cfg.profileChooserDMenu})"
|
||||
case "$profile" in
|
||||
"DEFAULT")
|
||||
${getExe pkgs.qutebrowser} $@
|
||||
;;
|
||||
${concatMapStringsSep "\n" (n: let
|
||||
profileDir = "${config.xdg.dataHome}/qutebrowser-profiles/${n}";
|
||||
in ''
|
||||
"${n}")
|
||||
${getExe pkgs.qutebrowser} -B ${profileDir} -C ${profileDir}/config.py --desktop-file-name qutebrowser-profile-${n} $@
|
||||
;;
|
||||
'')
|
||||
profiles}
|
||||
esac
|
||||
'';
|
||||
userscript = pkgs.writeShellScriptBin "qutebrowser-profiles-userscript" ''
|
||||
function close() {
|
||||
echo "close" >> "$QUTE_FIFO"
|
||||
}
|
||||
${getExe chooser} & close
|
||||
'';
|
||||
in
|
||||
mkIf (cfg.enable && cfg.profiles != {}) {
|
||||
programs.qutebrowser.package = pkgs.stdenv.mkDerivation {
|
||||
inherit (pkgs.qutebrowser) name pname meta;
|
||||
buildCommand = let
|
||||
desktopEntry = pkgs.makeDesktopItem {
|
||||
name = "qutebrowser";
|
||||
desktopName = "qutebrowser";
|
||||
exec = "${getExe (
|
||||
if cfg.profileChooser == "override"
|
||||
then chooser
|
||||
else pkgs.package
|
||||
)} %u";
|
||||
};
|
||||
chooserDesktopEntry = pkgs.makeDesktopItem {
|
||||
name = "qutebrowser chooser";
|
||||
desktopName = "qutebrowser-chooser";
|
||||
exec = "${getExe chooser} %u";
|
||||
};
|
||||
in ''
|
||||
mkdir -p $out/bin
|
||||
cp ${getExe pkgs.qutebrowser} $out/bin
|
||||
${
|
||||
if cfg.profileChooser != false
|
||||
then "cp ${getExe chooser} $out/bin"
|
||||
else ""
|
||||
}
|
||||
|
||||
mkdir -p $out/share/applications
|
||||
cp ${desktopEntry}/share/applications/qutebrowser.desktop $out/share/applications/qutebrowser.desktop
|
||||
${
|
||||
if cfg.profileChooser == true
|
||||
then "cp ${chooserDesktopEntry}/share/applications/qutebrowser-chooser.desktop $out/share/applications/qutebrowser-chooser.desktop"
|
||||
else ""
|
||||
}
|
||||
'';
|
||||
dontBuild = true;
|
||||
};
|
||||
|
||||
xdg.desktopEntries = mergeAttrsList (mapAttrsToList (n: v: let
|
||||
profileDir = "qutebrowser-profiles/${n}";
|
||||
in {
|
||||
"qutebrowser-profile-${n}" = {
|
||||
name =
|
||||
if isNull v.desktopName
|
||||
then "${
|
||||
if isNull v.name
|
||||
then n
|
||||
else v.name
|
||||
} (qutebrowser profile)"
|
||||
else v.desktopName;
|
||||
exec =
|
||||
"${getExe pkgs.qutebrowser}"
|
||||
+ " -B ${config.xdg.dataHome}/${profileDir}"
|
||||
+ " -C ${config.xdg.dataHome}/${profileDir}/config.py"
|
||||
+ " --desktop-file-name qutebrowser-profile-${n}"
|
||||
+ " %u";
|
||||
};
|
||||
})
|
||||
cfg.profiles);
|
||||
|
||||
xdg.dataFile = mergeAttrsList (mapAttrsToList (n: v: let
|
||||
profileDir = "qutebrowser-profiles/${n}";
|
||||
in {
|
||||
"${profileDir}/config.py" = {
|
||||
text = concatStringsSep "\n" (
|
||||
[
|
||||
(
|
||||
if v.loadAutoconfig
|
||||
then "config.load_autoconfig()"
|
||||
else "config.load_autoconfig(False)"
|
||||
)
|
||||
]
|
||||
++ lib.optional (v.titleFormat != "") ''
|
||||
c.window.title_format = '${replaceStrings ["{profile}" "{profile_name}"] [
|
||||
n
|
||||
(
|
||||
if isNull v.name
|
||||
then n
|
||||
else v.name
|
||||
)
|
||||
]
|
||||
v.titleFormat}'
|
||||
''
|
||||
++ lib.optional (v.extendDefault) ''
|
||||
config.source(r'${config.xdg.configHome}/qutebrowser/config.py')
|
||||
''
|
||||
++ mapAttrsToList (formatLine "c.") v.settings
|
||||
++ mapAttrsToList (formatDictLine "c.aliases") v.aliases
|
||||
++ mapAttrsToList (formatDictLine "c.url.searchengines") v.searchEngines
|
||||
++ mapAttrsToList (formatDictLine "c.bindings.key_mappings") v.keyMappings
|
||||
++ lib.optional (!v.enableDefaultBindings) "c.bindings.default = {}"
|
||||
++ mapAttrsToList formatKeyBindings v.keyBindings
|
||||
++ lib.optional (cfg.profileChooserUserscript != "" && !(isNull cfg.profileChooserUserscript))
|
||||
"config.bind(\"${cfg.profileChooserUserscript}\", \"spawn --userscript ${getExe userscript}\", mode=\"normal\")"
|
||||
++ lib.optional (v.extraConfig != "") cfg.extraConfig
|
||||
);
|
||||
onChange = ''
|
||||
hash="$(echo -n "$USER" | md5sum | cut -d' ' -f1)"
|
||||
socket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/qutebrowser/ipc-$hash"
|
||||
if [[ -S $socket ]]; then
|
||||
command=${
|
||||
lib.escapeShellArg (
|
||||
builtins.toJSON {
|
||||
args = [":config-source"];
|
||||
target_arg = null;
|
||||
protocol_version = 1;
|
||||
}
|
||||
)
|
||||
}
|
||||
echo "$command" | ${pkgs.socat}/bin/socat -lf /dev/null - UNIX-CONNECT:"$socket"
|
||||
fi
|
||||
unset hash socket command
|
||||
'';
|
||||
};
|
||||
|
||||
"${profileDir}/quickmarks" = mkIf (v.quickmarks != {}) {
|
||||
text = concatStringsSep "\n" (
|
||||
mapAttrsToList formatQuickmarks v.quickmarks
|
||||
);
|
||||
};
|
||||
|
||||
"${profileDir}/data/greasemonkey" = mkIf (v.greasemonkey != []) {
|
||||
source = pkgs.linkFarmFromDrvs "greasemonkey-userscripts" v.greasemonkey;
|
||||
};
|
||||
})
|
||||
cfg.profiles);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user