Compare commits

...

5 Commits

10 changed files with 1589 additions and 132 deletions

1074
flake.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,11 @@
inputs.nixpkgs.follows = "nixpkgs";
};
jj-cz = {
url = "git+https://labs.phundrak.com/phundrak/jj-cz";
inputs.nixpkgs.follows = "nixpkgs";
};
pumo-system-info = {
url = "git+https://labs.phundrak.com/phundrak/pumo-system-info";
inputs.nixpkgs.follows = "nixpkgs";
@@ -56,8 +61,22 @@
};
nixConfig = {
extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
extra-substituters = "https://devenv.cachix.org";
extra-trusted-public-keys = [
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
"phundrak.cachix.org-1:osJAkYO0ioTOPqaQCIXMfIRz1/+YYlVFkup3R2KSexk="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
extra-substituters = [
"https://nix-community.cachix.org?priority=10"
"https://devenv.cachix.org?priority=20"
"https://phundrak.cachix.org?priority=30"
"https://cache.nixos.org?priority=40"
];
extra-experimental-features = [
"nix-command"
"flakes"
];
http-connections = 128;
};
outputs = {

View File

@@ -6,10 +6,10 @@
}: let
name = "Handy";
pname = lib.strings.toLower name;
version = "0.7.7";
version = "0.8.0";
src = fetchurl {
url = "https://github.com/cjpais/${name}/releases/download/v${version}/${name}_${version}_amd64.AppImage";
hash = "sha256-76Hno39I3+46blnVW6XWwg944vF5n7IdMYXGMlYMNb0=";
hash = "sha256-PLcssfd6iMx51mglAJ7D4+67HFazwfhJMImgU9WiNDk=";
};
appimageContent = appimageTools.extractType2 {inherit pname version src;};
in

View File

@@ -36,10 +36,33 @@ in {
boot.tmp.cleanOnBoot = true;
console.keyMap = cfg.keymap;
time.timeZone = cfg.timezone;
environment.pathsToLink = ["/share/bash-completion" "/share/zsh"];
environment.pathsToLink = [
"/share/bash-completion"
"/share/zsh"
];
services = {
orca.enable = false;
envfs.enable = true;
};
nix.settings = {
substituters = [
"https://nix-community.cachix.org?priority=10"
"https://devenv.cachix.org?priority=20"
"https://phundrak.cachix.org?priority=30"
"https://cache.nixos.org?priority=40"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
"phundrak.cachix.org-1:osJAkYO0ioTOPqaQCIXMfIRz1/+YYlVFkup3R2KSexk="
];
http-connections = 128;
experimental-features = [
"nix-command"
"flakes"
];
};
};
}

View File

@@ -48,6 +48,10 @@ in {
enable = mkDefault true;
inherit (cfg) name email editor;
signing.sshKey = mkDefault (cfg.publicKey.file or cfg.publicKey.content);
cz = {
enable = mkDefault true;
alias = mkDefault true;
};
};
};
}

View File

@@ -2,10 +2,13 @@
lib,
config,
pkgs,
inputs,
...
}:
with lib; let
inherit (pkgs.stdenv.hostPlatform) system;
cfg = config.home.dev.vcs.jj;
jj-cz = inputs.jj-cz.packages.${system}.default;
in {
options.home.dev.vcs.jj = {
enable = mkEnableOption "enables jj";
@@ -33,83 +36,91 @@ in {
description = "Path to the private SSH key for signing.";
};
};
cz = {
enable = mkEnableOption "Enables jj-cz";
alias = mkEnableOption "Enable `jj cz` as an alias to `jj-cz`";
};
};
config.programs.jujutsu = mkIf cfg.enable {
enable = true;
settings = {
user = {
inherit (cfg) name email;
};
ui = {
default-command = "st";
pager = ":builtin";
show-cryptographic-signatures = true;
diff-editor = ":builtin";
merge-editort = ":builtin";
inherit (cfg) editor;
};
signing = mkIf cfg.signing.enable {
behavior = "own";
backend = "ssh";
key = cfg.signing.sshKey;
backends.ssh.allowed-signers = "${config.home.homeDirectory}/.ssh/allowed_signers";
backends.ssh.program = "${pkgs.openssh}/bin/ssh-keygen";
};
aliases = {
blame = ["file" "annotate"];
consume = ["squash" "--into" "@" "--from"];
eject = ["squash" "--from" "@" "--into"];
d = ["diff"];
dm = ["desc" "-m"];
gc = ["git" "clone"];
gcc = ["git" "clone" "--colocate"];
l = ["log"];
la = ["log" "-r" "::"];
lc = ["log" "-r" "(remote_bookmarks()..@)::"];
ll = ["log" "-T" "builtin_log_detailed"];
open = ["log" "-r" "open()"];
n = ["new"];
nd = ["new" "dev()"];
nt = ["new" "trunk()"];
revlog = ["evolog"];
s = ["show"];
tug = ["bookmark" "move" "--from" "heads(::@- & bookmarks())" "--to" "@-"];
};
colors.working_copy.underline = true;
git = {
private-commits = "blacklist()";
colocate = true;
subprocess = true;
};
revset-aliases = {
"immutable_heads()" = "present(trunk()) | tags()";
# Resolves by default to latest main/master remote bookmarks
"trunk()" = "latest((present(main) | present(master)) & remote_bookmarks())";
# Same as trunk() but for `dev` or `develop` bookmarks
"dev()" = "latest((present(dev) | present(develop)) & remote_bookmarks())";
config = mkIf cfg.enable {
home.packages = mkIf cfg.cz.enable [jj-cz];
programs.jujutsu = {
enable = true;
settings = {
user = {
inherit (cfg) name email;
};
ui = {
default-command = "st";
pager = ":builtin";
show-cryptographic-signatures = true;
diff-editor = ":builtin";
merge-editort = ":builtin";
inherit (cfg) editor;
};
signing = mkIf cfg.signing.enable {
behavior = "own";
backend = "ssh";
key = cfg.signing.sshKey;
backends.ssh.allowed-signers = "${config.home.homeDirectory}/.ssh/allowed_signers";
backends.ssh.program = "${pkgs.openssh}/bin/ssh-keygen";
};
aliases = {
blame = ["file" "annotate"];
consume = ["squash" "--into" "@" "--from"];
cz = mkIf cfg.cz.alias ["util" "exec" "--" "${jj-cz}/bin/jj-cz"];
eject = ["squash" "--from" "@" "--into"];
d = ["diff"];
dm = ["desc" "-m"];
gc = ["git" "clone"];
gcc = ["git" "clone" "--colocate"];
l = ["log"];
la = ["log" "-r" "::"];
lc = ["log" "-r" "(remote_bookmarks()..@)::"];
ll = ["log" "-T" "builtin_log_detailed"];
open = ["log" "-r" "open()"];
n = ["new"];
nd = ["new" "dev()"];
nt = ["new" "trunk()"];
revlog = ["evolog"];
s = ["show"];
tug = ["bookmark" "move" "--from" "heads(::@- & bookmarks())" "--to" "@-"];
};
colors.working_copy.underline = true;
git = {
private-commits = "blacklist()";
colocate = true;
subprocess = true;
};
revset-aliases = {
"immutable_heads()" = "present(trunk()) | tags()";
# Resolves by default to latest main/master remote bookmarks
"trunk()" = "latest((present(main) | present(master)) & remote_bookmarks())";
# Same as trunk() but for `dev` or `develop` bookmarks
"dev()" = "latest((present(dev) | present(develop)) & remote_bookmarks())";
"user(x)" = "author(x) | committer(x)";
"gh_pages()" = "ancestors(remote_bookmarks(exact:\"gh-pages\"))";
"user(x)" = "author(x) | committer(x)";
"gh_pages()" = "ancestors(remote_bookmarks(exact:\"gh-pages\"))";
#Private and WIP commits that should never be pushed
"wip()" = "description(glob:\"wip:*\")";
"private()" = "description(glob:\"private:*\")";
"blacklist()" = "wip() | private()";
#Private and WIP commits that should never be pushed
"wip()" = "description(glob:\"wip:*\")";
"private()" = "description(glob:\"private:*\")";
"blacklist()" = "wip() | private()";
# stack(x, n) is the set of mutable commits reachable from
# 'x', with 'n' parents. 'n' is often useful to customize the
# display and return set for certain operations. 'x' can be
# used to target the set of 'roots' to traverse, e.g. @ is the
# current stack.
"stack()" = "ancestors(reachable(@, mutable()), 2)";
"stack(x)" = "ancestors(reachable(x, mutable()), 2)";
"stack(x, n)" = "ancestors(reachable(x, mutable()), n)";
# stack(x, n) is the set of mutable commits reachable from
# 'x', with 'n' parents. 'n' is often useful to customize the
# display and return set for certain operations. 'x' can be
# used to target the set of 'roots' to traverse, e.g. @ is the
# current stack.
"stack()" = "ancestors(reachable(@, mutable()), 2)";
"stack(x)" = "ancestors(reachable(x, mutable()), 2)";
"stack(x, n)" = "ancestors(reachable(x, mutable()), n)";
"open()" = "stack(dev().. & mine(), 1)";
"ready()" = "open() ~ blacklist()::";
"open()" = "stack(dev().. & mine(), 1)";
"ready()" = "open() ~ blacklist()::";
};
remotes.origin.auto-track-bookmarks = "*";
};
remotes.origin.auto-track-bookmarks = "*";
};
};
}

View File

@@ -78,6 +78,7 @@ in {
./fish.nix
./starship.nix
./tmux.nix
./zellij.nix
./zsh.nix
./zoxide.nix
];

View File

@@ -0,0 +1,173 @@
{
pkgs,
lib,
config,
...
}:
with lib; let
cfg = config.home.shell.zellij;
isEmpty = list: list == [];
keybind = {
options = {
bind = mkOption {
type = types.either types.str (types.listOf types.str);
example = "Alt j";
description = "Value used as a string after `bind` in zellij config";
};
actions = mkOption {
type = with types; let
allowed = oneOf [int str];
in
attrsOf (either (listOf allowed) allowed);
default = {};
example = {
SwitchToMode = ["normal"];
SwitchFocus = [];
PaneNameInput = [0];
};
};
useUnlockFirst = mkOption {
type = types.bool;
default = false;
description = ''
Go back to locked mode after the actions are done.
Only works when `config.home.shell.zellij.useUnlockFirst` is true.
'';
};
};
};
convertBind = item: {
bind = let
useUnlockFirst = cfg.useUnlockFirst && item.useUnlockFirst;
children =
mapAttrsToList (action: args: let
actualArgs =
if isEmpty args
then {}
else {_args = lists.toList args;};
in {"${action}" = actualArgs;})
(item.actions
// (
if useUnlockFirst
then {SwitchToMode = ["locked"];}
else {}
));
in {
_args = lists.toList item.bind;
_children = children;
};
};
keybindsModule = {
options = mergeAttrsList (forEach [
"normal"
"locked"
"resize"
"pane"
"move"
"tab"
"scroll"
"search"
"entersearch"
"renametab"
"renamepane"
"session"
"tmux"
]
(x: {
"${x}" = mkOption {
type = types.listOf (types.submodule keybind);
default = [];
};
}));
};
makeKeybinds = keybinds: let
values =
attrsets.concatMapAttrs (
mode: binds:
if (isEmpty binds)
then {}
else {
"${mode}"._children = lists.forEach binds convertBind;
}
)
keybinds;
in
if values == {}
then {}
else {
keybinds = values;
};
in {
options.home.shell.zellij = let
jsonFormat = pkgs.formats.yaml {};
in {
enable = mkEnableOption "Enable Zellij";
clearDefaultKeybinds = mkEnableOption "Clear default keybinds";
settings = mkOption {
inherit (jsonFormat) type;
default = {};
};
layouts = mkOption {
inherit (jsonFormat) type;
default = {};
};
extraSettings = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add to `$XDG_CONFIG_HOME/zellij/config.kdl`
'';
};
useUnlockFirst = mkEnableOption "Use Unlock-First (non-colliding) behaviour by default";
plugins = mkOption {
type = types.listOf (types.submodule plugin);
default = {};
example = [
{name = "about";}
{
name = "filepicker";
location = "zellij:strider";
options = {
cwd = "/";
};
}
];
};
keybinds = mkOption {
type = types.submodule keybindsModule;
default = {};
example = {
pane = [
{
bind = "c";
actions = [
{
action = "SwitchToMode";
args = ["renamepane"];
}
{
action = "PaneNameInput";
args = [0];
}
];
}
];
};
};
};
config.programs.zellij = mkIf cfg.enable {
inherit (cfg) enable layouts;
extraConfig = cfg.extraSettings;
settings = let
resetKeybinds =
if cfg.clearDefaultKeybinds
then {
keybinds._props.clear-defaults = true;
}
else {};
keybinds = makeKeybinds cfg.keybinds;
in
cfg.settings // resetKeybinds // keybinds;
};
}

View File

@@ -7,7 +7,7 @@
with lib; let
cfg = config.home.phundrak;
in {
imports = [../modules];
imports = [../modules ./zellij.nix];
options.home.phundrak = {
sshKey = {

264
users/phundrak/zellij.nix Normal file
View File

@@ -0,0 +1,264 @@
{lib, ...}: {
home.shell.zellij = with lib; {
enable = true;
clearDefaultKeybinds = true;
useUnlockFirst = true;
settings.copy_on_select = true;
extraSettings = ''
plugins {
about location="zellij:about"
compact-bar location="zellij:compact-bar"
configuration location="zellij:configuration"
filepicker location="zellij:strider" {
cwd "/"
}
plugin-manager location="zellij:plugin-manager"
session-manager location="zellij:session-manager"
status-bar location="zellij:status-bar"
strider location="zellij:strider"
tab-bar location="zellij:tab-bar"
welcome-screen location="zellij:session-manager" {
welcome_screen true
}
}
'';
keybinds = let
# bépo layout
left = ["c" "Left"];
down = ["t" "Down"];
up = ["s" "Up"];
right = ["r" "Right"];
numRow = ["\"" "«" "»" "(" ")" "@" "+" "-" "/" "*"];
in {
locked = [
{
bind = "Ctrl Alt g";
actions = {SwitchToMode = "normal";};
}
];
pane = [
{
bind = left;
actions = {MoveFocus = "Left";};
}
{
bind = down;
actions = {MoveFocus = "Down";};
}
{
bind = up;
actions = {MoveFocus = "Up";};
}
{
bind = right;
actions = {MoveFocus = "Right";};
}
{
bind = "n";
actions = {NewPane = [];};
useUnlockFirst = true;
}
{
bind = "T";
actions = {NewPane = "Down";};
useUnlockFirst = true;
}
{
bind = "R";
actions = {NewPane = "Right";};
useUnlockFirst = true;
}
{
bind = "S";
actions = {NewPane = "stacked";};
useUnlockFirst = true;
}
{
bind = "N";
actions = {SwitchToMode = "normal";};
}
{
bind = "e";
actions = {TogglePaneEmbedOrFloating = [];};
useUnlockFirst = true;
}
{
bind = "i";
actions = {TogglePanePinned = [];};
}
{
bind = "f";
actions = {ToggleFocusFullscreen = [];};
useUnlockFirst = true;
}
{
bind = "F";
actions = {ToggleFloatingPanes = [];};
}
{
bind = "q";
actions = {CloseFocus = [];};
useUnlockFirst = true;
}
{
bind = "p";
actions = {SwitchToMode = "normal";};
}
{
bind = "P";
actions = {
SwitchToMode = "renamepane";
PaneNameInput = 0;
};
}
{
bind = "z";
actions = {TogglePaneFrames = [];};
useUnlockFirst = true;
}
{
bind = "tab";
actions = {SwitchFocus = [];};
}
];
resize = [
{
bind = "n";
actions = {SwitchToMode = "locked";};
}
{
bind = left;
actions = {Resize = "Increase Left";};
}
{
bind = down;
actions = {Resize = "Increase Down";};
}
{
bind = up;
actions = {Resize = "Increase Up";};
}
{
bind = right;
actions = {Resize = "Increase Right";};
}
{
bind = "C";
actions = {Resize = "Decrease Left";};
}
{
bind = "T";
actions = {Resize = "Decrease Down";};
}
{
bind = "S";
actions = {Resize = "Decrease Up";};
}
{
bind = "R";
actions = {Resize = "Decrease Right";};
}
{
bind = "+";
actions = {Resize = "Increase";};
}
{
bind = "-";
actions = {Resize = "Decrease";};
}
];
move = [
{
bind = left;
actions = {MovePane = "left";};
}
{
bind = down;
actions = {MovePane = "down";};
}
{
bind = up;
actions = {MovePane = "up";};
}
{
bind = right;
actions = {MovePane = "right";};
}
{
bind = "m";
actions = {SwitchToMode = "normal";};
}
{
bind = ["n" "tab"];
actions = {MovePane = [];};
}
{
bind = "p";
actions = {MovePaneBackwards = [];};
}
];
tab =
[
{
bind = left ++ up;
actions = {GoToPreviousTab = [];};
}
{
bind = down ++ right;
actions = {GoToNextTab = [];};
}
{
bind = "[";
actions = {BreakPaneLeft = [];};
useUnlockFirst = true;
}
{
bind = "]";
actions = {BreakPaneRight = [];};
useUnlockFirst = true;
}
{
bind = "b";
actions = {BreakPane = [];};
useUnlockFirst = true;
}
{
bind = "n";
actions = {NewTab = [];};
useUnlockFirst = true;
}
{
bind = "R";
actions = {
SwitchToMode = "renametab";
TabNameInput = 0;
};
}
{
bind = "s";
actions = {ToggleActiveSyncTab = [];};
useUnlockFirst = true;
}
{
bind = "T";
actions = {SwitchToMode = "normal";};
}
{
bind = "x";
actions = {CloseTab = [];};
useUnlockFirst = true;
}
{
bind = "tab";
actions = {ToggleTab = [];};
}
]
++ (lists.imap1 (i: key: {
bind = key;
actions = {GoToTab = i;};
useUnlockFirst = true;
})
numRow);
};
};
}