From 40e3834b7fce6ab2cab08c036def55566e8531a0 Mon Sep 17 00:00:00 2001 From: js0ny Date: Tue, 25 Nov 2025 17:35:23 +0000 Subject: [PATCH] niri: app maps and edit-clipboard shortcuts --- home/dot_config/nvim/init.lua | 53 ++++++++++++++++++- .../desktop/wayland-wm/niri/keymaps.nix | 42 +++++++++++---- .../desktop/wayland-wm/niri/scripts.nix | 29 ++++++++++ .../desktop/wayland-wm/niri/window-rules.nix | 10 ++++ .../users/js0ny/programs/edit-clipboard.nix | 27 ++++++++++ 5 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/scripts.nix diff --git a/home/dot_config/nvim/init.lua b/home/dot_config/nvim/init.lua index 6bf03ce..69a460b 100644 --- a/home/dot_config/nvim/init.lua +++ b/home/dot_config/nvim/init.lua @@ -8,10 +8,21 @@ -- Entry point of neovim configuration require("config.options") + +local minimal = os.getenv("NVIM_MINIMAL") or os.getenv("EDITOR_POPUP") + +if minimal == "1" then + -- require("profiles.minimal") + vim.keymap.set("n", "", ":wq!", { noremap = true, silent = true }) + return +end + local term = os.getenv("TERM") or "" if vim.g.vscode then -- TODO: VSCode Neovim Integration require("profiles.vscode") -elseif term == "linux" then -- Under tty +-- Under tty +-- if under gui, the term will be set to linux as well, additional check required. +elseif term == "linux" and not vim.fn.has("gui_running") then require("profiles.tty") vim.cmd("colorscheme vim") -- Use minimal colorscheme else @@ -38,3 +49,43 @@ if vim.g.neovide then vim.g.neovide_light_radius = 5 vim.g.neovide_input_macos_option_key_is_meta = "only_left" end + +-- 存储输入法状态的变量 +vim.g.input_layout = nil + +-- 退出插入模式时:记录当前输入法并切换到英文 +local function fcitx2en() + -- 使用 fcitx5-remote -n 获取当前输入法名称 + local current_layout = vim.fn.system("fcitx5-remote -n") + -- 去除换行符 + vim.g.input_layout = vim.trim(current_layout) + + -- 切换到英文输入法 + vim.fn.system("fcitx5-remote -s keyboard-us") +end + +-- 进入插入模式时:恢复之前的输入法状态 +local function fcitx2zh() + -- 如果之前记录了输入法状态,则恢复 + if vim.g.input_layout ~= nil and vim.g.input_layout ~= "" then + vim.fn.system("fcitx5-remote -s " .. vim.g.input_layout) + end +end + +-- 设置 ttimeoutlen +vim.opt.ttimeoutlen = 150 + +-- 创建自动命令组 +local fcitx_group = vim.api.nvim_create_augroup("FcitxToggle", { clear = true }) + +-- 退出插入模式时切换到英文并记录状态 +vim.api.nvim_create_autocmd("InsertLeave", { + group = fcitx_group, + callback = fcitx2en, +}) + +-- 进入插入模式时恢复之前的输入法 +vim.api.nvim_create_autocmd("InsertEnter", { + group = fcitx_group, + callback = fcitx2zh, +}) diff --git a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/keymaps.nix b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/keymaps.nix index da2a2e6..3ba94e8 100644 --- a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/keymaps.nix +++ b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/keymaps.nix @@ -1,4 +1,9 @@ -{config, ...}: let +{ + config, + pkgs, + lib, + ... +}: let term = config.currentUser.defaultTerminal; termRunner = config.currentUser.defaultTerminalRunner; iconTheme = config.currentUser.iconTheme; @@ -7,8 +12,29 @@ launcher = "rofi"; kbdBacklightDev = config.currentHost.keyboardBacklightDevice; kbdBacklightStep = config.currentHost.keyboardBacklightStep; + nirictl = import ./scripts.nix {inherit pkgs;}; in { + home.packages = [ + nirictl.focusOrLaunch + ]; programs.niri.settings.binds = with config.lib.niri.actions; { + # === Application Runner === + "Mod+B".hotkey-overlay.title = "Focus or launch web browser"; + "Mod+B".action = spawn "${lib.getExe nirictl.focusOrLaunch}" "firefox" "firefox"; + "Mod+Shift+B".hotkey-overlay.title = "Launch web browser in private mode"; + "Mod+Shift+B".action = spawn "firefox" "--private-window"; + "Mod+Shift+A".hotkey-overlay.title = "Focus or launch CherryStudio (AI assistant)"; + "Mod+Shift+A".action = spawn "${lib.getExe nirictl.focusOrLaunch}" "CherryStudio" "cherry-studio"; + "Mod+O".hotkey-overlay.title = "Focus or launch Obsidian"; + "Mod+O".action = spawn "${lib.getExe nirictl.focusOrLaunch}" "obsidian" "obsidian"; + # TODO: Change "org.kde.dolphin" to a more generic explorer app id via config.currentUser + "Mod+E".hotkey-overlay.title = "Focus or launch file explorer"; + "Mod+E".action = spawn "${lib.getExe nirictl.focusOrLaunch}" "org.kde.dolphin" "dolphin"; + + "Mod+Semicolon".action = spawn "neovide" "${config.home.homeDirectory}/Atelier"; + "Mod+Apostrophe".action = + spawn-sh "EDITOR_MINIMAL=1 ${termRunner} -o close_on_child_death=yes --class=edit-clipboard-popup -e edit-clipboard --minimal"; + "Mod+Shift+Slash".action = show-hotkey-overlay; "Mod+Return".hotkey-overlay.title = "Open a Terminal: ${term}"; @@ -22,17 +48,12 @@ in { "Alt+Space".action = spawn "${launcher}" "-show" "drun" "-icon-theme" "${iconTheme}" "-show-icons"; - "Mod+Shift+W".hotkey-overlay.title = "Search open Window: rofi"; - "Mod+Shift+W".action = + "Mod+W".hotkey-overlay.title = "Search open Window: rofi"; + "Mod+W".action = spawn "${launcher}" "-show" "window" "-icon-theme" "${iconTheme}" "-show-icons"; "Mod+V".action = spawn-sh "cliphist list | ${launcher} -dmenu | cliphist decode | wl-copy"; - "Mod+E".hotkey-overlay.title = "Run file explorer"; - "Mod+E".action = spawn "${explorer}"; - "Mod+Shift+E".hotkey-overlay.title = "Run terminal explorer"; - "Mod+Shift+E".action = spawn "${termRunner}" "-e" "${explorerTerm}"; - "XF86AudioRaiseVolume".allow-when-locked = true; "XF86AudioRaiseVolume".action = spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; @@ -174,8 +195,6 @@ in { "Mod+BracketLeft".action = consume-or-expel-window-left; "Mod+BracketRight".action = consume-or-expel-window-right; - "Mod+Comma".action = consume-window-into-column; - "Mod+Period".action = expel-window-from-column; "Mod+R".action = switch-preset-column-width; "Mod+Shift+R".action = switch-preset-window-height; @@ -191,7 +210,8 @@ in { "Mod+Shift+Equal".action = set-window-height "+10%"; "Mod+F".action = toggle-window-floating; "Mod+Shift+F".action = switch-focus-between-floating-and-tiling; - "Mod+W".action = toggle-column-tabbed-display; + "Mod+G".hotkey-overlay.title = "Toggle Grouped Display"; + "Mod+G".action = toggle-column-tabbed-display; "Mod+Shift+S".action.screenshot = {show-pointer = true;}; "Print".action.screenshot = {show-pointer = true;}; diff --git a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/scripts.nix b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/scripts.nix new file mode 100644 index 0000000..79d7e6e --- /dev/null +++ b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/scripts.nix @@ -0,0 +1,29 @@ +# Stolen from basecamp/omarchy +{pkgs, ...}: { + focusOrLaunch = pkgs.writeShellApplication { + name = "nirictl-focus-or-launch"; + + runtimeInputs = [pkgs.jq pkgs.niri]; + + text = '' + + if (($# == 0)); then + echo "Usage: $0 " >&2 + exit 1 + fi + + APP_ID="$1" + CMD="''${2:-$1}" + + WINDOWS=$(niri msg --json windows) + + TARGET_ID=$(echo "$WINDOWS" | jq -r ".[] | select(.app_id == \"$APP_ID\") | .id" | head -n 1) + + if [ -n "$TARGET_ID" ]; then + niri msg action focus-window --id "$TARGET_ID" + else + eval "$CMD" & + fi + ''; + }; +} diff --git a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/window-rules.nix b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/window-rules.nix index 79ebf25..c442ec5 100644 --- a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/window-rules.nix +++ b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri/window-rules.nix @@ -2,6 +2,16 @@ {...}: { programs.niri = { settings.window-rules = [ + { + matches = [ + { + app-id = "^edit-clipboard-popup$"; + } + ]; + + open-floating = true; + opacity = 0.8; + } # {{{ float, opacity 0.8, top right: Picture-in-Picture // waybar childs { matches = [ diff --git a/nixcfgs/users/js0ny/programs/edit-clipboard.nix b/nixcfgs/users/js0ny/programs/edit-clipboard.nix index 99f1bbe..e45da76 100644 --- a/nixcfgs/users/js0ny/programs/edit-clipboard.nix +++ b/nixcfgs/users/js0ny/programs/edit-clipboard.nix @@ -5,6 +5,31 @@ # Reads clipboard content, opens it in $EDITOR, and writes back to clipboard edit-clipboard() { + # Parse command line arguments + while [ $# -gt 0 ]; do + case "$1" in + --minimal) + NVIM_MINIMAL=1 + shift + ;; + --editor) + if [ -n "$2" ] && [ "''${2#-}" = "$2" ]; then + EDITOR="$2" + shift 2 + else + echo "Error: --editor requires an argument" >&2 + return 1 + fi + ;; + *) + echo "Error: Unknown option: $1" >&2 + echo "Usage: edit-clipboard [--popup] [--editor ]" >&2 + return 1 + ;; + esac + done + + # Detect clipboard command based on platform if command -v pbpaste >/dev/null 2>&1; then # macOS @@ -57,6 +82,8 @@ # Cleanup rm -f "$TMPFILE" + + exit 0 } if [ "''${0##*/}" = "edit-clipboard" ] || [ "''${0##*/}" = "edit-clipboard.sh" ]; then