Compare commits
20
Commits
aa17de12ac
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f404c4410f | ||
|
|
84b09c0e48 | ||
|
|
67ef3a3059 | ||
|
|
d085d60bad | ||
|
|
4b51cf4253 | ||
|
|
1b0c38a8d1 | ||
|
|
02dcab9871 | ||
|
|
1ec951997b | ||
|
|
eb82be6847 | ||
|
|
fbf7f3716d | ||
|
|
5a09671d0e | ||
|
|
ff21471623 | ||
|
|
3a350b4f15 | ||
|
|
10df55cded | ||
|
|
e138d87f2c | ||
|
|
6fe5f1a047 | ||
|
|
2f7cc0f43d | ||
|
|
cdf8164ed8 | ||
|
|
ee68c858fb | ||
|
|
19da4a0f06 |
@@ -1,5 +1,4 @@
|
||||
[general]
|
||||
enable-osc8=true
|
||||
log-file=~/aerc.log
|
||||
|
||||
[ui]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
[Settings]
|
||||
gtk-theme-name=Adwaita-dark
|
||||
gtk-icon-theme-name=Qogir-dark
|
||||
gtk-theme-name=Arc-Dark
|
||||
gtk-icon-theme-name=Qogir-Dark
|
||||
gtk-font-name=Noto Sans 10
|
||||
gtk-cursor-theme-name=Qogir-dark
|
||||
gtk-cursor-theme-size=0
|
||||
gtk-cursor-theme-name=Qogir-Dark
|
||||
gtk-cursor-theme-size=20
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-button-images=0
|
||||
@@ -12,5 +12,6 @@ gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle=hintmedium
|
||||
gtk-xft-hintstyle=hintslight
|
||||
gtk-xft-rgba=rgb
|
||||
gtk-application-prefer-dark-theme=1
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
vim.opt_local.number = true
|
||||
vim.opt_local.relativenumber = true
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Indentation & Layout
|
||||
vim.opt_local.colorcolumn = "100"
|
||||
vim.opt_local.textwidth = 100
|
||||
vim.opt_local.tabstop = 4
|
||||
vim.opt_local.shiftwidth = 4
|
||||
vim.opt_local.softtabstop = 4
|
||||
vim.opt_local.expandtab = true
|
||||
|
||||
-- Formatting Behavior
|
||||
vim.opt_local.formatoptions:remove("t") -- Don't autowrap while typing
|
||||
vim.opt_local.formatoptions:append("j") -- Remove comment markers when joining lines
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Indentation & Layout
|
||||
vim.opt_local.colorcolumn = "120"
|
||||
vim.opt_local.textwidth = 120
|
||||
vim.opt_local.tabstop = 4
|
||||
vim.opt_local.shiftwidth = 4
|
||||
vim.opt_local.softtabstop = 4
|
||||
vim.opt_local.expandtab = true
|
||||
|
||||
-- Formatting Behavior
|
||||
vim.opt_local.formatoptions:remove("t") -- Don't autowrap while typing
|
||||
vim.opt_local.formatoptions:append("j") -- Remove comment markers when joining lines
|
||||
@@ -0,0 +1,21 @@
|
||||
local bufname = vim.api.nvim_buf_get_name(0)
|
||||
local filename_arg = bufname ~= "" and (" --stdin-filepath " .. vim.fn.shellescape(bufname)) or ""
|
||||
|
||||
-- Indentation & Layout
|
||||
vim.opt_local.colorcolumn = ""
|
||||
vim.opt_local.wrap = true
|
||||
vim.opt_local.textwidth = 80
|
||||
vim.opt_local.tabstop = 2
|
||||
vim.opt_local.shiftwidth = 2
|
||||
vim.opt_local.softtabstop = 2
|
||||
vim.opt_local.expandtab = true
|
||||
|
||||
-- Formatting Behavior: wrap text, keep comment/quote headers, parse lists
|
||||
vim.opt_local.formatoptions:append("tqn")
|
||||
|
||||
-- gq Formatter: Prettier handles links/parentheses cleanly; par as fallback
|
||||
if vim.fn.executable("prettier") == 1 then
|
||||
vim.bo.formatprg = "prettier --parser markdown" .. filename_arg
|
||||
elseif vim.fn.executable("par") == 1 then
|
||||
vim.bo.formatprg = "par -w80req"
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Indentation & Layout
|
||||
vim.opt_local.colorcolumn = "100"
|
||||
vim.opt_local.textwidth = 100
|
||||
vim.opt_local.tabstop = 4
|
||||
vim.opt_local.shiftwidth = 4
|
||||
vim.opt_local.softtabstop = 4
|
||||
vim.opt_local.expandtab = true
|
||||
|
||||
-- Formatting Behavior
|
||||
vim.opt_local.formatoptions:remove("t") -- Don't autowrap while typing
|
||||
vim.opt_local.formatoptions:append("j") -- Remove comment markers when joining lines
|
||||
@@ -1,2 +0,0 @@
|
||||
vim.o.number = true
|
||||
vim.o.relativenumber = true
|
||||
@@ -1,4 +0,0 @@
|
||||
vim.o.colorcolumn = "100"
|
||||
vim.opt.tabstop = 4
|
||||
vim.opt.shiftwidth = 4
|
||||
vim.opt.softtabstop = 4
|
||||
@@ -1,4 +0,0 @@
|
||||
vim.o.colorcolumn = "120"
|
||||
vim.opt.tabstop = 4
|
||||
vim.opt.shiftwidth = 4
|
||||
vim.opt.softtabstop = 4
|
||||
@@ -1,5 +0,0 @@
|
||||
vim.o.colorcolumn = ""
|
||||
vim.o.wrap = true
|
||||
vim.opt.tabstop = 2
|
||||
vim.opt.shiftwidth = 2
|
||||
vim.opt.softtabstop = 2
|
||||
@@ -1,5 +0,0 @@
|
||||
vim.o.colorcolumn = "100"
|
||||
vim.opt.tabstop = 4
|
||||
vim.opt.shiftwidth = 4
|
||||
vim.opt.softtabstop = 4
|
||||
vim.g.no_python_maps = 1
|
||||
+12
-16
@@ -83,7 +83,7 @@ vim.opt.spelllang = { "en" }
|
||||
|
||||
-- Splits
|
||||
vim.opt.splitbelow = true
|
||||
vim.opt.splitkeep = "screen"
|
||||
vim.opt.splitkeep = "cursor"
|
||||
vim.opt.splitright = true
|
||||
|
||||
-- Terminal & Status Column
|
||||
@@ -118,6 +118,7 @@ vim.api.nvim_create_autocmd("FileType", {
|
||||
-- MAPS
|
||||
-- ----------------------------------------
|
||||
|
||||
vim.g.no_python_maps = 1
|
||||
local map = vim.keymap.set
|
||||
|
||||
-- better esc
|
||||
@@ -832,10 +833,7 @@ local function makespec_diffview()
|
||||
"DiffviewRefresh",
|
||||
"DiffviewFileHistory",
|
||||
},
|
||||
keys = {
|
||||
{ "<leader>gd", "<cmd>DiffviewOpen<cr>", desc = "DiffView Tab" },
|
||||
{ "<leader>gh", "<cmd>DiffviewFileHistory<cr>", desc = "File History Tab" },
|
||||
},
|
||||
keys = {},
|
||||
}
|
||||
end
|
||||
local function makespec_fugitive()
|
||||
@@ -883,6 +881,7 @@ local function makespec_gitsigns()
|
||||
vim.cmd.normal({ "]c", bang = true })
|
||||
else
|
||||
gs.nav_hunk("next")
|
||||
vim.schedule(gs.preview_hunk_inline)
|
||||
end
|
||||
end
|
||||
local function prev_hunk()
|
||||
@@ -890,14 +889,14 @@ local function makespec_gitsigns()
|
||||
vim.cmd.normal({ "[c", bang = true })
|
||||
else
|
||||
gs.nav_hunk("prev")
|
||||
vim.schedule(gs.preview_hunk_inline)
|
||||
end
|
||||
end
|
||||
|
||||
local function bmap(mode, l, r, desc) vim.keymap.set(mode, l, r, { buffer = bufnr, desc = desc }) end
|
||||
|
||||
-- Navigation
|
||||
bmap("n", "<M-,>", next_hunk, "Next Hunk")
|
||||
bmap("n", "<M-.>", prev_hunk, "Prev Hunk")
|
||||
bmap("n", "<M-,>", prev_hunk, "Prev Hunk")
|
||||
bmap("n", "<M-.>", next_hunk, "Next Hunk")
|
||||
bmap("n", "[h", prev_hunk, "Prev Hunk")
|
||||
bmap("n", "]h", next_hunk, "Next Hunk")
|
||||
|
||||
@@ -908,6 +907,8 @@ local function makespec_gitsigns()
|
||||
-- Hunk
|
||||
bmap("n", "<leader>gi", gs.preview_hunk_inline, "Preview Hunk Inline")
|
||||
bmap("n", "<leader>gp", gs.preview_hunk, "Preview Hunk")
|
||||
bmap("n", "<leader>gd", gs.diffthis, "Diff This (Index)")
|
||||
bmap("n", "<leader>gD", function() gs.diffthis("~") end, "Diff This (HEAD~1)")
|
||||
bmap("n", "<leader>gq", gs.setqflist, "File Hunks to QuickFix")
|
||||
bmap("n", "<leader>gQ", function() gs.setqflist("all") end, "All Hunks to QuickFix")
|
||||
bmap("n", "<leader>gx", gs.reset_hunk, "Reset Hunk")
|
||||
@@ -925,7 +926,7 @@ local function makespec_gitsigns()
|
||||
bmap("n", "<leader>gtb", gs.toggle_current_line_blame, "Toggle Line Blame")
|
||||
bmap("n", "<leader>gtd", gs.toggle_deleted, "Toggle Deleted")
|
||||
|
||||
-- Text object, e.g. for dih to delete hunk
|
||||
-- Text Object (e.g., 'dih' to delete hunk)
|
||||
bmap({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", "Select Hunk")
|
||||
end
|
||||
|
||||
@@ -933,11 +934,6 @@ local function makespec_gitsigns()
|
||||
"lewis6991/gitsigns.nvim",
|
||||
event = { "BufReadPre", "BufNewFile" },
|
||||
opts = {
|
||||
signcolumn = true,
|
||||
numhl = false,
|
||||
linehl = false,
|
||||
word_diff = false,
|
||||
signs_staged_enable = false,
|
||||
on_attach = on_gitsigns_attach,
|
||||
},
|
||||
}
|
||||
@@ -1100,8 +1096,8 @@ local function makespec_snacks()
|
||||
-- search
|
||||
{ "<F1>", function() Snacks.picker.help() end, desc = "Help Pages" },
|
||||
{ "<F9>", function() Snacks.picker.colorschemes() end, desc = "Colorschemes" },
|
||||
{ "<M-/>", function() Snacks.picker.git_grep({ ignorecase = true }) end, desc = "Grep Git Files" },
|
||||
{ "<leader>sg", function() Snacks.picker.git_grep({ ignorecase = true }) end, desc = "Grep Git Files" },
|
||||
{ "<M-/>", function() Snacks.picker.git_grep({ ignorecase = false }) end, desc = "Grep Git Files" },
|
||||
{ "<leader>sg", function() Snacks.picker.git_grep({ ignorecase = false }) end, desc = "Grep Git Files" },
|
||||
{ "<leader>sa", function() Snacks.picker.grep({ untracked = true }) end, desc = "Grep Files" },
|
||||
{ "<leader>*", function() Snacks.picker.grep_word() end, desc = "Visual selection or word", mode = { "n", "x" }, },
|
||||
{ "<leader>/", function() Snacks.picker.search_history() end, desc = "Search History" },
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import TYPE_CHECKING
|
||||
import os
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from qutebrowser.config.config import ConfigContainer
|
||||
@@ -6,7 +7,6 @@ if TYPE_CHECKING:
|
||||
|
||||
c: "ConfigContainer" = c # type: ignore # noqa: F821
|
||||
config: "ConfigAPI" = config # type: ignore # noqa: F821
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
config.load_autoconfig(True)
|
||||
config.bind("<", "tab-move -")
|
||||
@@ -47,7 +47,6 @@ config.bind("tj", "back -t", mode="normal")
|
||||
config.bind("wj", "back -w", mode="normal")
|
||||
config.bind("tk", "forward -t", mode="normal")
|
||||
config.bind("wk", "forward -w", mode="normal")
|
||||
config.bind("ø", "cmd-set-text :")
|
||||
config.bind("m", 'cmd-set-text :quickmark-add {url:pretty} "', mode="normal")
|
||||
config.bind("D", "tab-close")
|
||||
config.bind(",m", "hint links spawn -d mpv {hint-url}", mode="normal")
|
||||
@@ -73,7 +72,7 @@ c.completion.open_categories = [
|
||||
c.content.register_protocol_handler = False
|
||||
c.content.blocking.enabled = True
|
||||
c.content.fullscreen.window = True
|
||||
c.content.blocking.method = "adblock"
|
||||
c.content.blocking.method = "auto"
|
||||
c.content.blocking.adblock.lists = [
|
||||
"https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt",
|
||||
"https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/badware.txt",
|
||||
@@ -150,13 +149,21 @@ c.input.insert_mode.plugins = True
|
||||
c.messages.timeout = 5000
|
||||
c.qt.force_platform = "wayland"
|
||||
c.qt.highdpi = True
|
||||
c.qt.args = [
|
||||
qt_args = [
|
||||
"disable-features=WebAuth", # makes BankID work
|
||||
"disable-gpu", # Stops using the GPU for rendering
|
||||
"disable-gpu-compositing", # Forces CPU compositing
|
||||
"disable-accelerated-2d-canvas", # Offloads canvas drawing to CPU
|
||||
"disable-accelerated-video-decode", # Prevents VRAM usage for videos
|
||||
]
|
||||
# Disable GPU by default (for AI training), unless QUTE_ENABLE_GPU is set
|
||||
if os.environ.get("QUTE_ENABLE_GPU") != "1":
|
||||
qt_args.extend(
|
||||
[
|
||||
"disable-gpu", # Stops using the GPU for rendering
|
||||
"disable-gpu-compositing", # Forces CPU compositing
|
||||
"disable-accelerated-2d-canvas", # Offloads canvas drawing to CPU
|
||||
"disable-accelerated-video-decode", # Prevents VRAM usage for videos
|
||||
]
|
||||
)
|
||||
|
||||
c.qt.args = qt_args
|
||||
c.scrolling.bar = "always"
|
||||
c.scrolling.smooth = False
|
||||
c.session.lazy_restore = False
|
||||
@@ -190,16 +197,16 @@ c.tabs.undo_stack_size = 1000
|
||||
c.tabs.width = "15%"
|
||||
c.url.start_pages = "https://www.google.com/search?hl=en&source=hp"
|
||||
c.url.default_page = "https://www.google.com/search?hl=en&source=hp"
|
||||
c.url.searchengines = dict(
|
||||
DEFAULT="https://www.google.com/search?hl=en&source=hp&q={}",
|
||||
aw="https://wiki.archlinux.org/?search={}",
|
||||
ap="https://www.archlinux.org/packages/?q={}",
|
||||
gh="https://github.com/search?q={}&type=repositories",
|
||||
ip="https://iplocation.io/ip/{}",
|
||||
sh="https://explainshell.com/explain?cmd={}",
|
||||
wi="https://en.wikipedia.org/w/index.php?search={}",
|
||||
yt="https://yewtu.be/search?q={}",
|
||||
)
|
||||
c.url.searchengines = {
|
||||
"DEFAULT": "https://www.google.com/search?hl=en&source=hp&q={}",
|
||||
"aw": "https://wiki.archlinux.org/?search={}",
|
||||
"ap": "https://www.archlinux.org/packages/?q={}",
|
||||
"gh": "https://github.com/search?q={}&type=repositories",
|
||||
"ip": "https://iplocation.io/ip/{}",
|
||||
"sh": "https://explainshell.com/explain?cmd={}",
|
||||
"wi": "https://en.wikipedia.org/w/index.php?search={}",
|
||||
"yt": "https://yewtu.be/search?q={}",
|
||||
}
|
||||
c.zoom.default = "100%"
|
||||
|
||||
# FONTS
|
||||
|
||||
+20
-24
@@ -20,6 +20,9 @@ smart_borders on
|
||||
# Default Font
|
||||
font pango:Noto Sans Regular 10
|
||||
|
||||
# Cursor
|
||||
seat seat0 xcursor_theme Adwaita 0
|
||||
|
||||
# Title format for windows
|
||||
set $focus #00E5FF
|
||||
set $unfocused #333333
|
||||
@@ -182,8 +185,8 @@ bindsym --whole-window --border {
|
||||
# media keys
|
||||
bindsym {
|
||||
# Volume
|
||||
XF86AudioRaiseVolume exec pamixer -ui 2
|
||||
XF86AudioLowerVolume exec pamixer -ud 2
|
||||
XF86AudioRaiseVolume exec pamixer --unmute -i 2
|
||||
XF86AudioLowerVolume exec pamixer --unmute -d 2
|
||||
XF86AudioMute exec pamixer --toggle-mute
|
||||
Pause exec pamixer -ui 2
|
||||
Print exec pamixer -ud 2
|
||||
@@ -251,6 +254,7 @@ bindsym {
|
||||
|
||||
# Launch the browser
|
||||
$mod+i exec qutebrowser
|
||||
$mod+Shift+i exec env QUTE_ENABLE_GPU=1 qutebrowser
|
||||
|
||||
# Launch the file explorer
|
||||
$mod+o exec pcmanfm
|
||||
@@ -291,17 +295,10 @@ exec systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CU
|
||||
exec hash dbus-update-activation-environment 2>/dev/null && \
|
||||
dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
|
||||
|
||||
# Idle configuration
|
||||
exec swayidle -w \
|
||||
timeout 1200 'gtklock -d' \
|
||||
timeout 2400 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
|
||||
timeout 10 'if pgrep -x gtklock; then swaymsg "output * power off"; fi' \
|
||||
before-sleep 'gtklock -d'
|
||||
|
||||
# Start foot server
|
||||
exec systemctl --user enable --now foot-server.service
|
||||
|
||||
exec {
|
||||
# Start foot server
|
||||
exec systemctl --user enable --now foot-server.service
|
||||
|
||||
# Set wallpaper
|
||||
~/.azotebg
|
||||
|
||||
@@ -316,21 +313,21 @@ exec {
|
||||
|
||||
# night-time color shift
|
||||
wlsunset -l 59.91:10.76
|
||||
|
||||
# persist clipboard after close
|
||||
wl-clip-persist --clipboard regular --all-mime-type-regex '(?i)^(?!image/x-inkscape-svg).+'
|
||||
}
|
||||
|
||||
exec_always {
|
||||
pkill -x swaync; exec swaync
|
||||
pkill -x swayidle; exec swayidle -w \
|
||||
timeout 1200 'gtklock -d' \
|
||||
timeout 2400 'swaymsg "output * dpms off"' \
|
||||
resume 'swaymsg "output * dpms on"' \
|
||||
before-sleep 'gtklock -d' \
|
||||
lock 'gtklock -d'
|
||||
|
||||
# nwg-drawer
|
||||
nwg-drawer -r -c 7 -is 90 -mb 10 -ml 50 -mr 50 -mt 10
|
||||
|
||||
# persist clipboard after close
|
||||
pkill -x wl-clip-persist
|
||||
wl-clip-persist --clipboard regular --all-mime-type-regex '(?i)^(?!image/x-inkscape-svg).+'
|
||||
|
||||
# enable noisetorch
|
||||
noisetorch -u
|
||||
noisetorch -i
|
||||
}
|
||||
|
||||
# ------------------------------------------
|
||||
@@ -360,9 +357,8 @@ for_window [app_id="org.mozilla.Thunderbird" title="^((?!Mozilla Thunderbird).)*
|
||||
|
||||
# steam
|
||||
# https://github.com/ValveSoftware/steam-for-linux/issues/1040
|
||||
for_window [app_id="^steam$"] floating enable
|
||||
for_window [app_id="^Steam$"] floating enable
|
||||
for_window [app_id="^steam$" title="^Steam$"] floating disable
|
||||
for_window [app_id="(?i)^steam$"] floating enable
|
||||
for_window [app_id="(?i)^steam$" title="^Steam$"] floating disable
|
||||
|
||||
# Inhibit idle
|
||||
for_window [app_id="firefox"] inhibit_idle fullscreen
|
||||
|
||||
@@ -36,6 +36,15 @@ button:hover {
|
||||
border-bottom: 1px solid @border;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background: @urgent;
|
||||
}
|
||||
.widget-dnd,
|
||||
.widget-mpris,
|
||||
.widget-volume,
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ bind generic um status-merge
|
||||
bind generic - stage-update-line
|
||||
bind generic \ stage-split-chunk
|
||||
|
||||
bind generic y @sh -c "echo -n %(commit) | wl-copy"
|
||||
bind generic Y @sh -c "echo -n %(commit) | wl-copy"
|
||||
|
||||
bind generic c none
|
||||
bind generic cc !git commit
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"format-ok": "Systemd ✓",
|
||||
"system": true, // Monitor failed systemwide units.
|
||||
"user": true, // Ignore failed user units.
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 120x45 isd'"
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 250x45 systemctl-tui'"
|
||||
},
|
||||
|
||||
// Configuration - modules-right
|
||||
@@ -82,19 +82,19 @@
|
||||
"warning": 70,
|
||||
"critical": 90,
|
||||
},
|
||||
"on-click": "footclient --app-id floating_shell --window-size-chars 120x45 -e btop"
|
||||
"on-click": "footclient --app-id floating_shell --window-size-chars 250x150 -e btop"
|
||||
},
|
||||
|
||||
"temperature": {
|
||||
"critical-threshold": 80,
|
||||
"format": " {temperatureC}°C",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 80x45 -e watch sensors'"
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 120x100 -e watch sensors'"
|
||||
},
|
||||
|
||||
"memory": {
|
||||
"interval": 5,
|
||||
"format": "{:>3}%",
|
||||
"on-click": "footclient --app-id floating_shell --window-size-chars 100x100 -e btop",
|
||||
"on-click": "footclient --app-id floating_shell --window-size-chars 250x150 -e btop",
|
||||
"states": {
|
||||
"warning": 70,
|
||||
"critical": 90
|
||||
@@ -106,7 +106,7 @@
|
||||
"interval": 30,
|
||||
"format": " / {specific_free:0.0f} of {specific_total:0.0f} GB free",
|
||||
"unit": "GB",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 80x45 ncdu -x /'"
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 250x45 gdu -d'"
|
||||
},
|
||||
|
||||
"backlight": {
|
||||
@@ -132,7 +132,6 @@
|
||||
},
|
||||
"on-click": "pavucontrol",
|
||||
"tooltip-format": "{icon} {volume}% {format_source}",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 120x12 pulsemixer'",
|
||||
"on-click-middle": "pactl set-sink-mute @DEFAULT_SINK@ toggle",
|
||||
"on-scroll-up": "pactl set-sink-volume @DEFAULT_SINK@ +5%",
|
||||
"on-scroll-down": "pactl set-sink-volume @DEFAULT_SINK@ -5%"
|
||||
@@ -150,6 +149,27 @@
|
||||
"format-icons": ["", "", "", "", ""]
|
||||
},
|
||||
|
||||
"custom/notification": {
|
||||
"tooltip": true,
|
||||
"format": "<span size='16pt'>{icon}</span>",
|
||||
"format-icons": {
|
||||
"notification": "",
|
||||
"none": "",
|
||||
"dnd-notification": "",
|
||||
"dnd-none": "",
|
||||
"inhibited-notification": "",
|
||||
"inhibited-none": "",
|
||||
"dnd-inhibited-notification": "",
|
||||
"dnd-inhibited-none": ""
|
||||
},
|
||||
"return-type": "json",
|
||||
"exec-if": "which swaync-client",
|
||||
"exec": "swaync-client -swb",
|
||||
"on-click": "swaync-client -t -sw",
|
||||
"on-click-right": "swaync-client -d -sw",
|
||||
"escape": true
|
||||
},
|
||||
|
||||
"clock": {
|
||||
"format": " {:%H:%M}",
|
||||
"format-alt": " {:%OI:%M %p}",
|
||||
|
||||
+39
-11
@@ -1,28 +1,56 @@
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "q"
|
||||
run = "close"
|
||||
on = "E"
|
||||
run = "shell 'exiftool %s | less' --block --confirm"
|
||||
desc = "View file metadata with Exiftool"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "q"
|
||||
run = "close"
|
||||
desc = "Close tab"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "l"
|
||||
run = "plugin smart-enter"
|
||||
on = "l"
|
||||
run = "plugin smart-enter"
|
||||
desc = "Enter the child directory, or open the file"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = [ "c", "m" ]
|
||||
run = "plugin chmod"
|
||||
on = [ "c", "m" ]
|
||||
run = "plugin chmod"
|
||||
desc = "Chmod on selected files"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "F"
|
||||
run = "plugin smart-filter"
|
||||
on = "F"
|
||||
run = "plugin smart-filter"
|
||||
desc = "Smart filter"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "M"
|
||||
on = "M"
|
||||
run = "plugin mount"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "T"
|
||||
run = "plugin toggle-pane max-preview"
|
||||
on = "T"
|
||||
run = "plugin toggle-pane max-preview"
|
||||
desc = "Maximize or restore the preview pane"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "C"
|
||||
run = "plugin ouch"
|
||||
desc = "Compress with ouch"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = [ "c", "a" ]
|
||||
run = 'shell --block -- catai -T %s | nvim -R -c "set bt=nofile ft=xml" -'
|
||||
desc = "catai: Dump selected files/folders into Neovim"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = [ "c", "x" ]
|
||||
run = """\
|
||||
shell --block -- zsh -c \"args=(); for p in \\\"\\$@\\\"; do args+=(-x \\\"\\$p\\\"); done; catai -T \
|
||||
\\\"\\${args[@]}\\\" | nvim -R -c \\\"set bt=nofile ft=xml\\\" -\" -- %s\
|
||||
"""
|
||||
desc = "catai: Dump current dir EXCEPT selected items"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = [ "c", "d" ]
|
||||
run = 'shell --block -- catai -T -d | nvim -R -c "set bt=nofile ft=xml" -'
|
||||
desc = "catai: Dump git dirty files into Neovim"
|
||||
|
||||
+85
-7
@@ -4,11 +4,6 @@ show_hidden = true
|
||||
sort_by = "natural"
|
||||
ratio = [ 1, 4, 5 ]
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "O"
|
||||
run = "open --interactive"
|
||||
desc = "Open with... (Interactive menu)"
|
||||
|
||||
[preview]
|
||||
wrap = "yes"
|
||||
image_delay = 50
|
||||
@@ -17,14 +12,93 @@ max_height = 1500
|
||||
|
||||
[open]
|
||||
prepend_rules = [
|
||||
# Directories
|
||||
{ mime = "inode/directory", use = [ "thunar", "pcmanfm", "open" ] },
|
||||
|
||||
# Text & Code
|
||||
{ url = "*.csv", use = "text" },
|
||||
{ url = "*.md", use = [ "glow", "nvim", "bat", "open" ] },
|
||||
{ url = "*.json", use = [ "jq", "nvim", "bat", "open" ] },
|
||||
{ mime = "text/*", use = [ "nvim", "bat", "open" ] },
|
||||
{ mime = "inode/x-empty", use = [ "nvim", "open" ] },
|
||||
|
||||
# PDF & Documents
|
||||
{ mime = "application/pdf", use = [ "zathura", "sioyek", "okular", "xournalpp", "chrome", "firefox", "open" ] },
|
||||
{ mime = "application/vnd.openxmlformats-officedocument.*", use = [ "libreoffice", "calligra", "open" ] },
|
||||
{ mime = "application/vnd.oasis.opendocument.*", use = [ "libreoffice", "calligra", "open" ] },
|
||||
|
||||
# Images
|
||||
{ mime = "image/heic", use = [ "swappy", "krita", "open" ] },
|
||||
{ mime = "image/*", use = [ "qimgv", "swappy", "krita", "open" ] },
|
||||
|
||||
# Video & Audio
|
||||
{ mime = "video/*", use = [ "mpv", "vlc", "open" ] },
|
||||
{ mime = "audio/*", use = [ "quodlibet", "mpv", "vlc", "open" ] },
|
||||
|
||||
# Archives
|
||||
{ mime = "application/zip", use = [ "ouch", "file-roller", "open" ] },
|
||||
{ mime = "application/x-tar", use = [ "ouch", "file-roller", "open" ] },
|
||||
{ mime = "application/gzip", use = [ "ouch", "file-roller", "open" ] },
|
||||
{ mime = "application/x-bzip*", use = [ "ouch", "file-roller", "open" ] },
|
||||
{ mime = "application/x-7z-compressed", use = [ "ouch", "file-roller", "open" ] },
|
||||
{ mime = "application/x-rar", use = [ "ouch", "file-roller", "open" ] },
|
||||
|
||||
# Web pages
|
||||
{ mime = "text/html", use = [ "qutebrowser", "firefox", "chrome", "w3m", "open" ] },
|
||||
|
||||
# JSON files
|
||||
# Certificates
|
||||
{ url = "*.{crt,pem,cer,der}", use = [ "cert", "nvim", "bat", "open" ] },
|
||||
|
||||
# Catch-all for any file (allows Exiftool on everything as a fallback)
|
||||
{ url = "*", use = [ "exiftool", "open" ] },
|
||||
]
|
||||
|
||||
[opener]
|
||||
# --- Text / Code (Blocking Terminal Apps) ---
|
||||
text = [
|
||||
{ run = "bat $@", block = true, desc = "bat" },
|
||||
{ run = "nvim $@", block = true, desc = "nvim" },
|
||||
{ run = "bat %s", block = true, desc = "bat" },
|
||||
{ run = "nvim %s", block = true, desc = "nvim" },
|
||||
]
|
||||
nvim = [ { run = "nvim %s", block = true, desc = "Neovim" } ]
|
||||
bat = [ { run = "bat %s", block = true, desc = "Bat" } ]
|
||||
glow = [ { run = "glow --pager %s", block = true, desc = "Glow" } ]
|
||||
jq = [ { run = "jq -C . %s | less -R", block = true, desc = "jq viewer" } ]
|
||||
cert = [ { run = "openssl x509 -text -noout -in %s | less", block = true, desc = "View Cert (openssl)" } ]
|
||||
|
||||
# --- PDFs (Orphaned GUI Apps) ---
|
||||
zathura = [ { run = "zathura %s", orphan = true, desc = "Zathura" } ]
|
||||
sioyek = [ { run = "sioyek %s", orphan = true, desc = "Sioyek" } ]
|
||||
okular = [ { run = "okular %s", orphan = true, desc = "Okular" } ]
|
||||
xournalpp = [ { run = "xournalpp %s", orphan = true, desc = "Xournal++" } ]
|
||||
|
||||
# --- Browsers (Orphaned GUI Apps) ---
|
||||
chrome = [ { run = "google-chrome-stable %s", orphan = true, desc = "Chrome" } ]
|
||||
firefox = [ { run = "firefox %s", orphan = true, desc = "Firefox" } ]
|
||||
qutebrowser = [ { run = "qutebrowser %s", orphan = true, desc = "Qutebrowser" } ]
|
||||
w3m = [ { run = "w3m %s", orphan = true, desc = "w3m" } ]
|
||||
|
||||
# --- Media: Video / Audio (Orphaned GUI Apps) ---
|
||||
mpv = [ { run = "mpv %s", orphan = true, desc = "MPV" } ]
|
||||
vlc = [ { run = "vlc %s", orphan = true, desc = "VLC" } ]
|
||||
quodlibet = [ { run = "quodlibet %s", orphan = true, desc = "quod libet" } ]
|
||||
|
||||
# --- Images (Orphaned GUI Apps) ---
|
||||
qimgv = [ { run = "qimgv %s", orphan = true, desc = "qimgv" } ]
|
||||
swappy = [ { run = "swappy -f %s", orphan = true, desc = "swappy" } ]
|
||||
krita = [ { run = "krita %s", orphan = true, desc = "krita" } ]
|
||||
|
||||
# --- Office Documents (Orphaned GUI Apps) ---
|
||||
libreoffice = [ { run = "libreoffice %s", orphan = true, desc = "LibreOffice" } ]
|
||||
calligra = [ { run = "calligrawords %s", orphan = true, desc = "Calligra" } ]
|
||||
|
||||
# --- Archives ---
|
||||
ouch = [ { run = "ouch d -y %s", desc = "Extract here with ouch" } ]
|
||||
file-roller = [ { run = "file-roller %s", orphan = true, desc = "File Roller" } ]
|
||||
|
||||
# --- Directories (Orphaned GUI Apps) ---
|
||||
thunar = [ { run = "thunar %s", orphan = true, desc = "Thunar" } ]
|
||||
pcmanfm = [ { run = "pcmanfm %s", orphan = true, desc = "PCManFM" } ]
|
||||
|
||||
[input]
|
||||
cursor_blink = true
|
||||
@@ -43,6 +117,10 @@ group = "git"
|
||||
url = "*/"
|
||||
run = "git"
|
||||
|
||||
[[plugin.prepend_previewers]]
|
||||
mime = "application/{*zip,tar,bzip2,7z*,rar,xz,zstd,java-archive}"
|
||||
run = "ouch"
|
||||
|
||||
[[plugin.prepend_previewers]]
|
||||
url = "*/"
|
||||
run = "eza-preview"
|
||||
|
||||
+9
-7
@@ -13,14 +13,16 @@ export SAVEHIST=200000
|
||||
alias ls='ls --color=auto -Ah'
|
||||
alias ..='cd ..'
|
||||
alias ...='cd ../..'
|
||||
catai () {
|
||||
rg -l --hidden --glob '!.git/*' --sort path '^' -- "$@" | while IFS= read -r f; do
|
||||
printf "\n── %s ──\n" "$f"
|
||||
echo '```'
|
||||
cat "$f"
|
||||
echo '```'
|
||||
done
|
||||
catai() {
|
||||
if [[ " $* " == *" -i "* || " $* " == *" -y "* ]]; then
|
||||
local cmd
|
||||
cmd="$(command catai --print-cmd "$@")" && [[ -n "$cmd" ]] && print -z "$cmd"
|
||||
else
|
||||
command catai "$@"
|
||||
fi
|
||||
}
|
||||
alias cataid='catai -d'
|
||||
alias cataiy='catai -y'
|
||||
alias sioyek="QT_QPA_PLATFORM=xcb sioyek"
|
||||
|
||||
# --- basic keybinds ---
|
||||
|
||||
Executable
+352
@@ -0,0 +1,352 @@
|
||||
#!/usr/bin/env python3.14
|
||||
"""
|
||||
catai: Collect project tree & files in XML tags for LLM context.
|
||||
|
||||
Requires Python >= 3.14 (PEP 649/749 deferred annotations, PEP 695 type statements).
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from collections.abc import Iterable, Sequence
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
type GlobList = list[str]
|
||||
type PathList = list[str]
|
||||
|
||||
DEFAULT_IGNORES: tuple[str, ...] = (
|
||||
"!.git/*",
|
||||
"!.env*",
|
||||
"!*lock*",
|
||||
"!*.lock",
|
||||
"!*.min.*",
|
||||
)
|
||||
|
||||
EXAMPLES = """
|
||||
Examples:
|
||||
catai # Dump entire current repo
|
||||
catai src/ # Dump everything inside src/
|
||||
catai src -x legacy # Everything in src/ except src/legacy/
|
||||
catai src -x '*.test.ts' -x dist # Exclude multiple patterns
|
||||
catai src '!legacy' '!*.spec.js' # Exclude using '!' shorthand
|
||||
catai -T src/main.rs # Single file without <project_tree>
|
||||
catai -i src -x vendor # Pick files in fzf
|
||||
catai -y # Pick files/folders in Yazi
|
||||
catai -d # Only git-modified & untracked files
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(slots=True, frozen=True)
|
||||
class Config:
|
||||
paths: PathList
|
||||
rg_globs: GlobList
|
||||
dirty: bool
|
||||
no_tree: bool
|
||||
interactive: bool
|
||||
yazi: bool
|
||||
print_cmd: bool
|
||||
|
||||
|
||||
def expand_exclude(pattern: str) -> GlobList:
|
||||
"""Expand a user exclusion pattern into ripgrep glob flags."""
|
||||
clean = pattern.lstrip("!").rstrip("/")
|
||||
if not clean:
|
||||
return []
|
||||
# Normalize absolute paths or leading './' so ripgrep globs match properly
|
||||
try:
|
||||
p = Path(clean)
|
||||
if p.is_absolute():
|
||||
clean = str(p.relative_to(Path.cwd()))
|
||||
elif clean.startswith("./"):
|
||||
clean = clean[2:]
|
||||
except ValueError:
|
||||
pass
|
||||
return [
|
||||
f"--glob=!{clean}",
|
||||
f"--glob=!{clean}/**",
|
||||
f"--glob=!**/{clean}",
|
||||
f"--glob=!**/{clean}/**",
|
||||
]
|
||||
|
||||
|
||||
def parse_args(argv: Sequence[str] | None = None) -> Config:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="catai",
|
||||
description="Collect project tree and files in XML tags for LLM context.",
|
||||
epilog=EXAMPLES,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument(
|
||||
"targets",
|
||||
nargs="*",
|
||||
help="Files, directories, or '!exclude' globs",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-x",
|
||||
"--exclude",
|
||||
action="append",
|
||||
default=[],
|
||||
metavar="PATTERN",
|
||||
help="Exclude folder or file glob (repeatable)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--dirty",
|
||||
action="store_true",
|
||||
help="Only git modified & untracked files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-T",
|
||||
"--no-tree",
|
||||
action="store_true",
|
||||
help="Skip <project_tree> header",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--interactive",
|
||||
action="store_true",
|
||||
help="Interactive fzf file picker",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-y",
|
||||
"--yazi",
|
||||
action="store_true",
|
||||
help="Interactive Yazi file/folder chooser",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--print-cmd",
|
||||
action="store_true",
|
||||
help="Print selected command instead of executing (used by zsh print -z)",
|
||||
)
|
||||
|
||||
ns = parser.parse_args(argv)
|
||||
|
||||
rg_globs: GlobList = [f"--glob={g}" for g in DEFAULT_IGNORES]
|
||||
for ex in ns.exclude:
|
||||
rg_globs.extend(expand_exclude(ex))
|
||||
|
||||
paths: PathList = []
|
||||
for target in ns.targets:
|
||||
match target:
|
||||
case s if s.startswith("!"):
|
||||
rg_globs.extend(expand_exclude(s[1:]))
|
||||
case s:
|
||||
paths.append(s)
|
||||
|
||||
return Config(
|
||||
paths=paths,
|
||||
rg_globs=rg_globs,
|
||||
dirty=ns.dirty,
|
||||
no_tree=ns.no_tree,
|
||||
interactive=ns.interactive,
|
||||
yazi=ns.yazi,
|
||||
print_cmd=ns.print_cmd,
|
||||
)
|
||||
|
||||
|
||||
def run_lines(cmd: Sequence[str]) -> list[str]:
|
||||
"""Run a command and return non-empty stdout lines."""
|
||||
res = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
||||
return [line for line in res.stdout.splitlines() if line]
|
||||
|
||||
|
||||
def render_tree(file_paths: Iterable[str]) -> str:
|
||||
"""Pure-Python directory tree renderer (no external 'tree' binary required)."""
|
||||
type TreeDict = dict[str, TreeDict]
|
||||
root: TreeDict = {}
|
||||
|
||||
for raw_path in sorted(file_paths):
|
||||
parts = Path(raw_path).parts
|
||||
curr = root
|
||||
for part in parts:
|
||||
if part in (".", ""):
|
||||
continue
|
||||
curr = curr.setdefault(part, {})
|
||||
|
||||
lines: list[str] = ["."]
|
||||
|
||||
def walk(node: TreeDict, prefix: str = "") -> None:
|
||||
items = list(node.items())
|
||||
for idx, (name, children) in enumerate(items):
|
||||
is_last = idx == len(items) - 1
|
||||
connector = "└── " if is_last else "├── "
|
||||
lines.append(f"{prefix}{connector}{name}")
|
||||
if children:
|
||||
extension = " " if is_last else "│ "
|
||||
walk(children, prefix + extension)
|
||||
|
||||
walk(root)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def pick_with_fzf(cfg: Config) -> PathList:
|
||||
rg_cmd = [
|
||||
"rg",
|
||||
"--files",
|
||||
"--hidden",
|
||||
"--sort",
|
||||
"path",
|
||||
*cfg.rg_globs,
|
||||
"--",
|
||||
*cfg.paths,
|
||||
]
|
||||
all_files = run_lines(rg_cmd)
|
||||
if not all_files:
|
||||
return []
|
||||
|
||||
preview = "bat --color=always {} 2>/dev/null || cat {}"
|
||||
proc = subprocess.run(
|
||||
["fzf", "-m", "--preview", preview],
|
||||
input="\n".join(all_files),
|
||||
stdout=subprocess.PIPE,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
return [line for line in proc.stdout.splitlines() if line]
|
||||
|
||||
|
||||
def pick_with_yazi(cfg: Config) -> PathList:
|
||||
with tempfile.NamedTemporaryFile(prefix="yazi-chooser.", delete=False) as tmp:
|
||||
tmp_path = Path(tmp.name)
|
||||
|
||||
try:
|
||||
subprocess.run(["yazi", f"--chooser-file={tmp_path}", *cfg.paths], check=False)
|
||||
if not tmp_path.exists() or tmp_path.stat().st_size == 0:
|
||||
return []
|
||||
raw_picked = [
|
||||
line for line in tmp_path.read_text(encoding="utf-8").splitlines() if line
|
||||
]
|
||||
cwd = Path.cwd()
|
||||
rel_picked: PathList = []
|
||||
for p in raw_picked:
|
||||
path_obj = Path(p)
|
||||
try:
|
||||
rel_picked.append(str(path_obj.relative_to(cwd)))
|
||||
except ValueError:
|
||||
rel_picked.append(str(path_obj))
|
||||
return rel_picked
|
||||
finally:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
|
||||
|
||||
def collect_files(cfg: Config, target_paths: PathList) -> tuple[PathList, PathList]:
|
||||
"""Return (tree_files, matched_non_empty_text_files)."""
|
||||
cwd = Path.cwd().resolve()
|
||||
rel_targets: PathList = []
|
||||
for p in target_paths:
|
||||
resolved = Path(p).resolve()
|
||||
try:
|
||||
rel = str(resolved.relative_to(cwd))
|
||||
rel_targets.append("." if rel == "" else rel)
|
||||
except ValueError:
|
||||
rel_targets.append(os.path.relpath(resolved, cwd))
|
||||
|
||||
if cfg.dirty:
|
||||
dirty_cmd = [
|
||||
"git",
|
||||
"ls-files",
|
||||
"-m",
|
||||
"-o",
|
||||
"--exclude-standard",
|
||||
"--",
|
||||
*rel_targets,
|
||||
]
|
||||
candidates = run_lines(dirty_cmd)
|
||||
if not candidates:
|
||||
return [], []
|
||||
else:
|
||||
candidates = rel_targets
|
||||
|
||||
# Non-empty, non-binary files via ripgrep '^'
|
||||
rg_content_cmd = [
|
||||
"rg",
|
||||
"-l",
|
||||
"--hidden",
|
||||
"--sort",
|
||||
"path",
|
||||
*cfg.rg_globs,
|
||||
"^",
|
||||
"--",
|
||||
*candidates,
|
||||
]
|
||||
matched_files = run_lines(rg_content_cmd)
|
||||
|
||||
# Single-file edge case: `rg -l '^' single_file.txt` prints the filename,
|
||||
# Ensure it is always included if non-empty
|
||||
if cfg.no_tree or not matched_files:
|
||||
return [], matched_files
|
||||
|
||||
rg_tree_cmd = [
|
||||
"rg",
|
||||
"--files",
|
||||
"--hidden",
|
||||
"--sort",
|
||||
"path",
|
||||
*cfg.rg_globs,
|
||||
"--",
|
||||
*rel_targets,
|
||||
]
|
||||
tree_files = run_lines(rg_tree_cmd)
|
||||
return tree_files, matched_files
|
||||
|
||||
|
||||
def dump_output(tree_files: PathList, files: PathList, show_tree: bool) -> None:
|
||||
out = sys.stdout
|
||||
if show_tree and tree_files:
|
||||
out.write("<project_tree>\n")
|
||||
out.write(render_tree(tree_files))
|
||||
out.write("\n</project_tree>\n\n")
|
||||
|
||||
for filepath in files:
|
||||
path = Path(filepath)
|
||||
out.write(f'<file path="{filepath}">\n')
|
||||
out.flush()
|
||||
try:
|
||||
with path.open("rb") as f:
|
||||
shutil.copyfileobj(f, sys.stdout.buffer)
|
||||
# Ensure trailing newline before closing tag
|
||||
if path.stat().st_size > 0:
|
||||
with path.open("rb") as f:
|
||||
f.seek(-1, os.SEEK_END)
|
||||
if f.read(1) != b"\n":
|
||||
out.write("\n")
|
||||
except OSError as exc:
|
||||
sys.stderr.write(f"Error reading {filepath}: {exc}\n")
|
||||
out.write("</file>\n\n")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
cfg = parse_args()
|
||||
|
||||
# Handle interactive pickers (-i / -y)
|
||||
if cfg.interactive or cfg.yazi:
|
||||
picked = pick_with_yazi(cfg) if cfg.yazi else pick_with_fzf(cfg)
|
||||
if not picked:
|
||||
return 1
|
||||
if cfg.print_cmd:
|
||||
print(f"catai {shlex.join(picked)}")
|
||||
return 0
|
||||
tree_files, files = collect_files(cfg, picked)
|
||||
else:
|
||||
tree_files, files = collect_files(cfg, cfg.paths)
|
||||
|
||||
if not files:
|
||||
msg = (
|
||||
"No dirty or untracked files found."
|
||||
if cfg.dirty
|
||||
else "No matching text files found."
|
||||
)
|
||||
sys.stderr.write(f"{msg}\n")
|
||||
return 1
|
||||
|
||||
dump_output(tree_files, files, show_tree=not cfg.no_tree)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -15,12 +15,12 @@
|
||||
"interval": 30,
|
||||
"format": " /mnt/hdd1 {specific_free:0.0f} of {specific_total:0.0f} GB free",
|
||||
"unit": "GB",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 80x45 ncdu -x /mnt/hdd1/'"
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 150x45 gdu -d'"
|
||||
},
|
||||
"custom/nvidia": {
|
||||
"exec": "nvidia-smi --query-gpu=utilization.gpu,memory.used,temperature.gpu --format=csv,nounits,noheader | sed 's/\\([0-9]\\+\\), \\([0-9]\\+\\), \\([0-9]\\+\\)/\\1% \\2MB \\3°C/g'",
|
||||
"format": " {}",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 120x45 nvtop'",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 150x45 watch nvidia-smi'",
|
||||
"interval": 1
|
||||
},
|
||||
"modules-right": [
|
||||
@@ -36,6 +36,7 @@
|
||||
"battery",
|
||||
"clock",
|
||||
"tray",
|
||||
"custom/power"
|
||||
"custom/notification",
|
||||
"custom/power",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
"interval": 30,
|
||||
"format": " /mnt/hdd1 {specific_free:0.0f} of {specific_total:0.0f} GB free",
|
||||
"unit": "GB",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 80x45 ncdu -x /mnt/hdd1/'"
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 150x45 gdu -d'"
|
||||
},
|
||||
"custom/nvidia": {
|
||||
"exec": "nvidia-smi --query-gpu=utilization.gpu,memory.used,temperature.gpu --format=csv,nounits,noheader | sed 's/\\([0-9]\\+\\), \\([0-9]\\+\\), \\([0-9]\\+\\)/\\1% \\2MB \\3°C/g'",
|
||||
"format": " {}",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 120x45 nvtop'",
|
||||
"on-click": "swaymsg exec 'footclient --app-id floating_shell --window-size-chars 150x45 watch nvidia-smi'",
|
||||
"interval": 1
|
||||
},
|
||||
"modules-right": [
|
||||
@@ -36,6 +36,7 @@
|
||||
"battery",
|
||||
"clock",
|
||||
"tray",
|
||||
"custom/power"
|
||||
"custom/notification",
|
||||
"custom/power",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"battery",
|
||||
"clock",
|
||||
"tray",
|
||||
"custom/power"
|
||||
"custom/notification",
|
||||
"custom/power",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"battery",
|
||||
"clock",
|
||||
"tray",
|
||||
"custom/power"
|
||||
"custom/notification",
|
||||
"custom/power",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -52,13 +52,12 @@ installmap = dict(
|
||||
tmux=("tmux", "urlscan"),
|
||||
editors=(
|
||||
"neovim",
|
||||
"helix",
|
||||
"ripgrep",
|
||||
"npm", # required for nvim plugins
|
||||
"go", # required for vim-hexokinase build
|
||||
"tree-sitter-cli", # required for nvim treesitter
|
||||
),
|
||||
utils=("uv", "ncdu", "unzip", "jq", "bluetui"),
|
||||
utils=("uv", "gdu", "unzip", "jq", "bluetui"),
|
||||
gittools=(
|
||||
"tig",
|
||||
"diff-so-fancy",
|
||||
@@ -92,19 +91,18 @@ installmap = dict(
|
||||
# photos
|
||||
"qimgv",
|
||||
"kimageformats5", # heif support
|
||||
"digikam",
|
||||
# music
|
||||
"quodlibet",
|
||||
"gst-plugins-good", # required deb
|
||||
# audio
|
||||
"pamixer",
|
||||
"noisetorch",
|
||||
),
|
||||
filebrowsers=(
|
||||
"yazi",
|
||||
"ranger",
|
||||
"pcmanfm",
|
||||
"thunar",
|
||||
"ouch",
|
||||
"gparted",
|
||||
"sshfs",
|
||||
"file-roller",
|
||||
@@ -122,7 +120,7 @@ installmap = dict(
|
||||
"python-tldextract",
|
||||
"bitwarden-cli", # for qutebrowser autofill
|
||||
),
|
||||
chat=("discordo-git", "gurk"),
|
||||
chat=("discord", "gurk"),
|
||||
emailcalrss=(
|
||||
"khard", # contacts
|
||||
"khal", # calendar
|
||||
@@ -138,8 +136,7 @@ installmap = dict(
|
||||
"htop", # hardware
|
||||
"btop", # hardware
|
||||
"nvtop", # gpu
|
||||
"lazyjournal", # journald
|
||||
"isd", # systemd
|
||||
"systemctl-tui", # systemd
|
||||
"bandwhich", # network
|
||||
"sysstat",
|
||||
),
|
||||
@@ -283,6 +280,7 @@ def install_zsh(overwrite: bool, reinstall: bool) -> None:
|
||||
run("chsh -s /usr/bin/zsh".split())
|
||||
helper_maybe_copy(CFG_SRC, CFG_TGT, "starship.toml", overwrite, symlink=True)
|
||||
helper_maybe_copy(HOME_SRC, HOME_TGT, ".zshenv", overwrite, symlink=True)
|
||||
helper_maybe_copy(HOME_SRC, HOME_TGT, ".local/bin/catai", overwrite, symlink=True)
|
||||
|
||||
|
||||
def install_tmux(overwrite: bool, reinstall: bool) -> None:
|
||||
@@ -301,7 +299,6 @@ def install_tmux(overwrite: bool, reinstall: bool) -> None:
|
||||
def install_editors(overwrite: bool, reinstall: bool) -> None:
|
||||
helper_install(*installmap["editors"], reinstall=reinstall)
|
||||
helper_clone_foldercontents(CFG_SRC, CFG_TGT, "nvim", overwrite)
|
||||
helper_clone_foldercontents(CFG_SRC, CFG_TGT, "helix", overwrite)
|
||||
|
||||
|
||||
def install_gittools(overwrite: bool, reinstall: bool) -> None:
|
||||
@@ -335,6 +332,7 @@ def install_filebrowsers(overwrite: bool, reinstall: bool) -> None:
|
||||
"yazi-rs/plugins:toggle-pane",
|
||||
"ahkohd/eza-preview",
|
||||
"boydaihungst/file-extra-metadata",
|
||||
"ya pkg add ndtoan96/ouch",
|
||||
]:
|
||||
run(f"ya pkg add {plugin}".split())
|
||||
tgt = ".local/share/applications/userapp-file-roller.desktop"
|
||||
@@ -350,7 +348,6 @@ def install_netbrowsers(overwrite: bool, reinstall: bool) -> None:
|
||||
|
||||
def install_chat(overwrite: bool, reinstall: bool) -> None:
|
||||
helper_install(*installmap["chat"], reinstall=reinstall)
|
||||
helper_clone_foldercontents(CFG_SRC, CFG_TGT, "discordo", overwrite)
|
||||
helper_clone_foldercontents(CFG_SRC, CFG_TGT, "gurk", overwrite)
|
||||
|
||||
|
||||
@@ -412,12 +409,12 @@ def install_sway(overwrite: bool, reinstall: bool) -> None:
|
||||
helper_clone_foldercontents(CFG_SRC, CFG_TGT, sub, overwrite)
|
||||
helper_maybe_copy(CFG_SRC, CFG_TGT, "xdg-terminals.list", overwrite, symlink=True)
|
||||
helper_maybe_copy(CFG_SRC, CFG_TGT, "mimeapps.list", overwrite, symlink=True)
|
||||
# swaync configs
|
||||
helper_clone_foldercontents(CFG_SRC, CFG_TGT, "swaync", overwrite)
|
||||
# custom sway configs
|
||||
helper_clone_foldercontents(CUSTOM_SRC / "CONFIG", CFG_TGT, "sway", overwrite)
|
||||
# custom waybar configs
|
||||
helper_clone_foldercontents(CUSTOM_SRC / "CONFIG", CFG_TGT, "waybar", overwrite)
|
||||
# custom swaync configs
|
||||
helper_clone_foldercontents(CUSTOM_SRC / "CONFIG", CFG_TGT, "swaync", overwrite)
|
||||
# desktop entries
|
||||
helper_clone_foldercontents(
|
||||
HOME_SRC,
|
||||
|
||||
Reference in New Issue
Block a user