Compare commits

4 Commits
Author SHA1 Message Date
Pierre MARTINandClaude Opus 5.5 967a31d574 feat(hyprland): session Hyprland en test à côté d'i3
- Hyprland via UWSM (comme Omarchy), à choisir à la connexion ;
  i3 reste la session par défaut
- config Lua (format Hyprland >= 0.55) : raccourcis bépo d'i3,
  apparence Omarchy, Ghostty comme terminal
- waybar, hyprlock, swaybg, grim/slurp, wl-clipboard, brightnessctl
- workspace-run : support de hyprctl et des options en --opt=
- stt-dictate : wtype sous Wayland au lieu de xdotool

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:33:19 +02:00
Pierre MARTINandClaude Opus 5.5 ac6ae897f4 feat(neovim): ajout de Neovim avec LazyVim (comme Omarchy)
Starter LazyVim versionné dans files/nvim, thème Catppuccin Mocha
(identique à Ghostty). Alias n = nvim ; vim reste l'$EDITOR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:31:59 +02:00
Pierre MARTINandClaude Opus 5.5 a97f97c548 feat(ghostty): ajout du terminal Ghostty (réglages Omarchy)
Police JetBrains Mono Nerd Font, thème Catppuccin Mocha, marges,
Shift+Entrée distinct d'Entrée pour les TUI. Sakura reste le terminal
d'i3 pour comparer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:31:32 +02:00
Pierre MARTINandClaude Opus 5.5 f6e5bf6e2f feat: reprise de choix d'Omarchy (outils CLI, git, polices)
- git : rerere, tri des branches/tags, commit.verbose, column.ui,
  diff.mnemonicPrefix
- CLI : eza (alias ls/ll/lt), fd, lazygit, lazydocker, alias ff
  (fzf + aperçu bat), lzg/lzd
- tmux : config de base (vi, souris, index 1, splits dans le cwd)
- système : polices JetBrains Mono Nerd Font, Noto, emoji et CJK

Non testé : pas de Nix sur la machine où ces changements ont été écrits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:27:02 +02:00
18 changed files with 391 additions and 9 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ NixOS dotfiles for Pierre MARTIN (Lundi Matin — Front-Commerce, LMB, NEIA), us
- `nixos/configuration.nix` — System-level NixOS config (bootloader, networking, services, system packages). Imports `hardware-configuration.nix` et `framework.nix`. - `nixos/configuration.nix` — System-level NixOS config (bootloader, networking, services, system packages). Imports `hardware-configuration.nix` et `framework.nix`.
- `home.nix` — Entry point home-manager. Importe `packages.nix` et les modules de `programs/`. Mappe aussi les fichiers statiques depuis `files/`. - `home.nix` — Entry point home-manager. Importe `packages.nix` et les modules de `programs/`. Mappe aussi les fichiers statiques depuis `files/`.
- `packages.nix` — Tous les packages utilisateur (avec allowlist unfree). - `packages.nix` — Tous les packages utilisateur (avec allowlist unfree).
- `programs/` — Modules home-manager par programme : `git.nix`, `zsh.nix`, `i3.nix`, `neia.nix`. - `programs/` — Modules home-manager par programme : `git.nix`, `zsh.nix`, `i3.nix`, `hyprland.nix`, `ghostty.nix`, `neovim.nix`, `pi.nix`.
- `files/` — Fichiers de config statiques copiés dans `$HOME` par home-manager (`.npmrc`, `traefik.toml`, etc.). - `files/` — Fichiers de config statiques copiés dans `$HOME` par home-manager (`.npmrc`, `traefik.toml`, etc.).
Home-manager est intégré au module NixOS (pas standalone). Appliquer avec `sudo nixos-rebuild switch`. Home-manager est intégré au module NixOS (pas standalone). Appliquer avec `sudo nixos-rebuild switch`.
@@ -46,7 +46,7 @@ Après modification de fichiers `.sh`, lancer `make fmt && make lint` avant d'ap
## Key details ## Key details
- Keyboard layout : bépo (`fr` variant `bepo`) - Keyboard layout : bépo (`fr` variant `bepo`)
- Window manager : i3 (Mod4) - Window manager : i3 (Mod4), session par défaut. Hyprland (Wayland, config Lua dans `files/hypr/hyprland.lua`) en test, mêmes raccourcis bépo
- Shell : zsh + oh-my-zsh + starship + mcfly - Shell : zsh + oh-my-zsh + starship + mcfly
- Terminal : sakura - Terminal : sakura
- Git : difftastic (diffs), meld (merges), `push.autoSetupRemote = true` - Git : difftastic (diffs), meld (merges), `push.autoSetupRemote = true`
+129
View File
@@ -0,0 +1,129 @@
-- Hyprland - https://wiki.hypr.land/Configuring/Start/
-- Raccourcis repris de programs/i3.nix (bépo), apparence reprise d'Omarchy :
-- https://github.com/basecamp/omarchy/tree/master/default/hypr
local mod = "SUPER"
local function bind(keys, dispatcher, options)
if type(dispatcher) == "string" then
dispatcher = hl.dsp.exec_cmd(dispatcher)
end
hl.bind(keys, dispatcher, options or {})
end
-- Écrans : détection automatique (remplace autorandr)
hl.monitor({ output = "", mode = "preferred", position = "auto", scale = "auto" })
hl.env("XCURSOR_SIZE", "24")
hl.env("GDK_BACKEND", "wayland,x11,*")
hl.env("QT_QPA_PLATFORM", "wayland;xcb")
hl.env("ELECTRON_OZONE_PLATFORM_HINT", "wayland")
hl.env("TERMINAL", "ghostty")
hl.config({
input = {
kb_layout = "fr",
kb_variant = "bepo",
follow_mouse = 1,
repeat_rate = 40,
repeat_delay = 250,
numlock_by_default = true,
touchpad = {
clickfinger_behavior = true,
scroll_factor = 0.4,
},
},
general = {
gaps_in = 5,
gaps_out = 10,
border_size = 2,
col = {
active_border = { colors = { "rgba(33ccffee)", "rgba(00ff99ee)" }, angle = 45 },
inactive_border = "rgba(595959aa)",
},
resize_on_border = true,
layout = "dwindle",
},
decoration = {
rounding = 0,
shadow = { enabled = false },
blur = { enabled = false },
},
animations = { enabled = true },
dwindle = {
preserve_split = true,
force_split = 2,
},
misc = {
disable_hyprland_logo = true,
disable_splash_rendering = true,
background_color = "rgb(000000)",
focus_on_activate = true,
},
-- Remplace unclutter
cursor = { inactive_timeout = 3 },
})
hl.on("hyprland.start", function()
hl.exec_cmd("waybar")
hl.exec_cmd("swaybg --mode fill --image /home/pierre/Documents/Graphisme/fc-bg-light-black.png")
hl.exec_cmd("copyq")
end)
-- Applications
bind(mod .. " + Return", "~/.local/bin/workspace-run ghostty --working-directory=")
bind(mod .. " + SHIFT + Return", "~/.local/bin/workspace-run code")
bind(mod .. " + d", "rofi -combi-modi 'window#run#ssh#emoji#calc' -modi 'calc#combi' -show combi")
bind(mod .. " + space", "~/.local/bin/stt-dictate toggle")
bind(mod .. " + SHIFT + t", "hyprlock")
bind("Print", "grim -g \"$(slurp)\" - | wl-copy")
bind("SHIFT + Print", "grim - | wl-copy")
-- Fenêtres (mêmes touches qu'i3 en bépo)
bind(mod .. " + b", hl.dsp.window.close())
bind(mod .. " + e", hl.dsp.window.fullscreen({ mode = "fullscreen" }))
bind(mod .. " + p", hl.dsp.layout("togglesplit"))
-- Pas de layout tabbed/stacking dans Hyprland : les groupes en sont l'équivalent
bind(mod .. " + eacute", hl.dsp.group.toggle())
bind(mod .. " + u", hl.dsp.group.next())
bind(mod .. " + SHIFT + space", hl.dsp.window.float({ action = "toggle" }))
for _, arrow in ipairs({ { "Left", "l" }, { "Right", "r" }, { "Up", "u" }, { "Down", "d" } }) do
local key, direction = arrow[1], arrow[2]
bind(mod .. " + " .. key, hl.dsp.focus({ direction = direction }))
bind(mod .. " + SHIFT + " .. key, hl.dsp.window.swap({ direction = direction }))
bind(mod .. " + CTRL + " .. key, hl.dsp.workspace.move({ monitor = direction }))
end
bind(mod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
bind(mod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })
-- Espaces de travail : keycodes 10 à 19 = rangée du haut, quelle que soit la
-- disposition (" « » ( ) @ + - / * en bépo)
for workspace = 1, 10 do
local key = "code:" .. tostring(workspace + 9)
bind(mod .. " + " .. key, hl.dsp.focus({ workspace = tostring(workspace) }))
bind(mod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = tostring(workspace) }))
end
-- Session
bind(mod .. " + SHIFT + c", "hyprctl reload")
bind(mod .. " + SHIFT + e", "uwsm stop")
-- Touches multimédia (actives même écran verrouillé)
local media = { locked = true, repeating = true }
bind("XF86AudioRaiseVolume", "pactl set-sink-volume @DEFAULT_SINK@ +5%", media)
bind("XF86AudioLowerVolume", "pactl set-sink-volume @DEFAULT_SINK@ -5%", media)
bind("XF86AudioMute", "pactl set-sink-mute @DEFAULT_SINK@ toggle", { locked = true })
bind("XF86AudioPlay", "playerctl play-pause", { locked = true })
bind("XF86AudioPause", "playerctl play-pause", { locked = true })
bind("XF86AudioNext", "playerctl next", { locked = true })
bind("XF86AudioPrev", "playerctl previous", { locked = true })
bind("XF86MonBrightnessUp", "brightnessctl set +5%", media)
bind("XF86MonBrightnessDown", "brightnessctl set 5%-", media)
+1
View File
@@ -0,0 +1 @@
require("config.lazy")
+1
View File
@@ -0,0 +1 @@
-- Voir https://www.lazyvim.org/configuration/general
+1
View File
@@ -0,0 +1 @@
-- Voir https://www.lazyvim.org/configuration/general
+31
View File
@@ -0,0 +1,31 @@
-- Starter LazyVim - https://github.com/LazyVim/starter
-- Les plugins sont téléchargés par lazy.nvim au premier lancement (hors Nix) :
-- lazy-lock.json est donc écrit dans ~/.config/nvim et n'est pas versionné.
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
spec = {
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
{ import = "plugins" },
},
defaults = {
lazy = false,
version = false,
},
install = { colorscheme = { "catppuccin", "habamax" } },
checker = { enabled = true, notify = false },
})
+1
View File
@@ -0,0 +1 @@
-- Voir https://www.lazyvim.org/configuration/general
+5
View File
@@ -0,0 +1,5 @@
-- Même thème que Ghostty
return {
{ "catppuccin/nvim", name = "catppuccin", opts = { flavour = "mocha" } },
{ "LazyVim/LazyVim", opts = { colorscheme = "catppuccin" } },
}
+4
View File
@@ -86,7 +86,11 @@ stop_and_transcribe() {
# Tape le texte au curseur # Tape le texte au curseur
if [[ -n "$TEXT" ]]; then if [[ -n "$TEXT" ]]; then
sleep 0.1 # petit delai pour focus sleep 0.1 # petit delai pour focus
if [[ -n "${WAYLAND_DISPLAY:-}" ]]; then
wtype -d 10 -- "$TEXT"
else
xdotool type --delay 10 -- "$TEXT" xdotool type --delay 10 -- "$TEXT"
fi
notify "$TEXT" notify "$TEXT"
else else
notify "Aucun texte detecte" notify "Aucun texte detecte"
+23 -5
View File
@@ -3,22 +3,35 @@
# Examples: # Examples:
# workspace-run.sh zeditor # workspace-run.sh zeditor
# workspace-run.sh sakura --working-directory # workspace-run.sh sakura --working-directory
# workspace-run.sh ghostty --working-directory= (un argument finissant par = est collé au dossier)
cmd=${1:?usage: workspace-run.sh <command> [args...]} cmd=${1:?usage: workspace-run.sh <command> [args...]}
shift shift
if [ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]; then
workspace=$(hyprctl activeworkspace -j | jq -r '.name')
else
workspace=$(i3-msg -t get_workspaces | jq -r '.[] | select(.focused) | .name') workspace=$(i3-msg -t get_workspaces | jq -r '.[] | select(.focused) | .name')
fi
window_pids() {
if [ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]; then
hyprctl clients -j | jq -r --arg ws "$workspace" '.[] | select(.workspace.name == $ws) | .pid'
return
fi
terminal_cwd() {
local wids local wids
wids=$(i3-msg -t get_tree | jq -r " wids=$(i3-msg -t get_tree | jq -r "
.nodes[].nodes[].nodes[] .nodes[].nodes[].nodes[]
| select(.name == \"$workspace\") | select(.name == \"$workspace\")
| .. | objects | select(.window? != null) | .window | .. | objects | select(.window? != null) | .window
") ")
for wid in $wids; do for wid in $wids; do
local pid xdotool getwindowpid "$wid" 2>/dev/null
pid=$(xdotool getwindowpid "$wid" 2>/dev/null) || continue done
}
terminal_cwd() {
for pid in $(window_pids); do
local shell_pid local shell_pid
shell_pid=$(pgrep -P "$pid" -x zsh | head -1) || continue shell_pid=$(pgrep -P "$pid" -x zsh | head -1) || continue
local cwd local cwd
@@ -35,4 +48,9 @@ if [ -z "$dir" ]; then
dir=$(grep "^${workspace}=" "$dir_file" 2>/dev/null | cut -d= -f2-) dir=$(grep "^${workspace}=" "$dir_file" 2>/dev/null | cut -d= -f2-)
fi fi
exec "$cmd" "$@" "${dir:-$HOME}" dir=${dir:-$HOME}
if [ $# -gt 0 ] && [[ "${!#}" == *= ]]; then
set -- "${@:1:$#-1}" "${!#}$dir"
exec "$cmd" "$@"
fi
exec "$cmd" "$@" "$dir"
+29
View File
@@ -52,14 +52,43 @@
imports = [ imports = [
./packages.nix ./packages.nix
./programs/ghostty.nix
./programs/git.nix ./programs/git.nix
./programs/hyprland.nix
./programs/i3.nix ./programs/i3.nix
./programs/neovim.nix
./programs/pi.nix ./programs/pi.nix
./programs/zsh.nix ./programs/zsh.nix
]; ];
programs.btop.enable = true; programs.btop.enable = true;
programs.vim.enable = true; programs.vim.enable = true;
# Outils CLI repris d'Omarchy - https://github.com/basecamp/omarchy
programs.eza = {
enable = true; # alias ls, ll, la, lt…
enableZshIntegration = true;
git = true;
icons = "auto";
};
programs.fd.enable = true;
programs.lazygit.enable = true;
programs.tmux = {
enable = true;
keyMode = "vi";
mouse = true;
baseIndex = 1;
escapeTime = 0;
historyLimit = 50000;
extraConfig = ''
# Nouveaux panneaux et fenêtres dans le répertoire courant
bind '"' split-window -v -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}"
set -g renumber-windows on
'';
};
programs.vscode = { programs.vscode = {
enable = true; enable = true;
package = pkgs.vscode.fhs; package = pkgs.vscode.fhs;
+16
View File
@@ -86,6 +86,14 @@
defaultSession = "none+i3"; defaultSession = "none+i3";
}; };
# Session Hyprland en test : à choisir sur l'écran de connexion.
# UWSM, comme Omarchy, lance les services de session (graphical-session.target).
programs.hyprland = {
enable = true;
withUWSM = true;
};
security.pam.services.hyprlock = { };
# Configure console keymap # Configure console keymap
console.keyMap = "fr"; console.keyMap = "fr";
@@ -125,6 +133,14 @@
]; ];
virtualisation.docker.enable = true; virtualisation.docker.enable = true;
# Polices reprises d'Omarchy : Nerd Font pour les icônes (eza, starship) + emoji et CJK
fonts.packages = with pkgs; [
nerd-fonts.jetbrains-mono
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
];
# Some programs need SUID wrappers, can be configured further or are # Some programs need SUID wrappers, can be configured further or are
# started in user sessions. # started in user sessions.
# programs.mtr.enable = true; # programs.mtr.enable = true;
+1
View File
@@ -144,6 +144,7 @@ in
bun bun
docker docker
docker-compose docker-compose
lazydocker
kubectl kubectl
kubernetes-helm kubernetes-helm
stern stern
+33
View File
@@ -0,0 +1,33 @@
{ ... }:
# Réglages repris d'Omarchy - https://github.com/basecamp/omarchy/blob/master/config/ghostty/config
{
programs.ghostty = {
enable = true;
enableZshIntegration = true;
settings = {
font-family = "JetBrainsMono Nerd Font";
font-size = 10;
theme = "Catppuccin Mocha";
window-padding-x = 14;
window-padding-y = 14;
confirm-close-surface = false;
resize-overlay = "never";
cursor-style = "block";
cursor-style-blink = false;
shell-integration-features = "no-cursor,ssh-env";
keybind = [
"shift+insert=paste_from_clipboard"
"control+insert=copy_to_clipboard"
# Distingue Shift+Entrée d'Entrée pour les TUI (Claude Code…)
"shift+enter=csi:13;2u"
];
# Lenteurs sous Hyprland - https://github.com/ghostty-org/ghostty/discussions/3224
async-backend = "epoll";
};
};
}
+11
View File
@@ -66,6 +66,17 @@
# see https://adamj.eu/tech/2022/10/15/how-to-rebase-stacked-git-branches/ # see https://adamj.eu/tech/2022/10/15/how-to-rebase-stacked-git-branches/
rebase.updateRefs = true; rebase.updateRefs = true;
# Repris d'Omarchy - https://github.com/basecamp/omarchy/blob/master/config/git/config
rerere = {
enabled = true; # mémorise la résolution des conflits…
autoupdate = true; # … et la réapplique automatiquement
};
branch.sort = "-committerdate"; # branches les plus récentes en premier
tag.sort = "-version:refname"; # tri des tags par version (v1.10 après v1.9)
column.ui = "auto";
commit.verbose = true; # diff affiché dans l'éditeur du message de commit
diff.mnemonicPrefix = true; # préfixes i/ w/ c/ au lieu de a/ b/
"url \"git@gitlab.lundimatin.app:\"" = { "url \"git@gitlab.lundimatin.app:\"" = {
insteadOf = "https://gitlab.lundimatin.app/"; insteadOf = "https://gitlab.lundimatin.app/";
}; };
+75
View File
@@ -0,0 +1,75 @@
{ pkgs, ... }:
# Session Hyprland, en test à côté d'i3. Le compositeur et la session sont
# activés côté système (programs.hyprland dans nixos/configuration.nix).
{
xdg.configFile."hypr/hyprland.lua".source = ../files/hypr/hyprland.lua;
home.packages = with pkgs; [
swaybg # fond d'écran (remplace feh)
grim # captures d'écran…
slurp # … d'une zone
wl-clipboard # wl-copy / wl-paste (remplace xsel)
wtype # saisie de texte (remplace xdotool), pour stt-dictate
brightnessctl # remplace xbacklight
];
# Lancée par hyprland.lua et pas par systemd, pour ne pas apparaître sous i3
programs.waybar = {
enable = true;
settings.main = {
layer = "top";
position = "top";
height = 26;
modules-left = [ "hyprland/workspaces" ];
modules-center = [ "clock" ];
modules-right = [
"cpu"
"temperature"
"disk"
"network"
"pulseaudio"
"battery"
"tray"
];
clock = {
format = "{:%a %d %b %H:%M}";
tooltip-format = "<tt>{calendar}</tt>";
};
cpu.format = "CPU {usage}%";
disk.format = "/ {percentage_used}%";
network = {
format-wifi = "{essid} {signalStrength}%";
format-ethernet = "{ipaddr}";
format-disconnected = "hors ligne";
};
pulseaudio = {
format = "vol {volume}%";
format-muted = "muet";
on-click = "pavucontrol";
};
battery.format = "bat {capacity}%";
};
};
programs.hyprlock = {
enable = true;
settings = {
general.hide_cursor = true;
background = [
{
color = "rgb(000000)";
}
];
input-field = [
{
size = "400, 60";
position = "0, 0";
halign = "center";
valign = "center";
placeholder_text = "Mot de passe";
}
];
};
};
}
+22
View File
@@ -0,0 +1,22 @@
{ pkgs, ... }:
# LazyVim, comme Omarchy. vim reste l'$EDITOR le temps de l'essai.
{
programs.neovim = {
enable = true;
# Compilation des parsers nvim-treesitter. Les LSP installés par Mason
# tournent grâce à programs.nix-ld (nixos/configuration.nix).
extraPackages = with pkgs; [
tree-sitter
gcc
unzip
];
};
# recursive : ~/.config/nvim reste un vrai dossier, où LazyVim écrit
# lazy-lock.json et lazyvim.json.
xdg.configFile."nvim" = {
source = ../files/nvim;
recursive = true;
};
}
+4
View File
@@ -116,10 +116,13 @@
s = "fzf"; # show / search / select s = "fzf"; # show / search / select
f = "fzf"; # file f = "fzf"; # file
sf = "fzf"; # interactive file selection sf = "fzf"; # interactive file selection
ff = "fzf --preview 'bat --style=numbers --color=always {}'"; # fzf avec aperçu (Omarchy)
dc = "docker compose"; dc = "docker compose";
dcr = "docker compose run --rm"; dcr = "docker compose run --rm";
dcrm = "docker compose rm -fsv"; dcrm = "docker compose rm -fsv";
lzd = "lazydocker";
lzg = "lazygit";
copy = "xclip -selection c"; copy = "xclip -selection c";
bepo = "setxkbmap -layout fr -variant bepo"; bepo = "setxkbmap -layout fr -variant bepo";
@@ -132,6 +135,7 @@
kp = "kubectl --context prod-eu7"; kp = "kubectl --context prod-eu7";
kp9 = "k9s --context prod-eu7"; kp9 = "k9s --context prod-eu7";
g = "git"; g = "git";
n = "nvim";
gui = "gitui"; gui = "gitui";
htop = "btop"; htop = "btop";
c = "claude"; c = "claude";