update
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
{...}:
|
||||
{
|
||||
home.file.alacritty = {
|
||||
target = ".config/alacritty/alacritty.toml";
|
||||
text = ''
|
||||
[general]
|
||||
import = ["dank-theme.toml"]
|
||||
|
||||
[window]
|
||||
padding = { x = 10, y = 10 }
|
||||
|
||||
[font]
|
||||
normal = { family = 'JetBrainsMono Nerd Font', style = 'Regular' }
|
||||
size = 11
|
||||
offset = { x = 1, y = 2}
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -141,6 +141,7 @@ hotkey-overlay {
|
||||
prefer-no-csd
|
||||
screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
|
||||
animations {
|
||||
off
|
||||
workspace-switch {
|
||||
spring damping-ratio=0.80 stiffness=523 epsilon=0.0001
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
niri.homeModules.niri
|
||||
dankMaterialShell.homeModules.dankMaterialShell.default
|
||||
dankMaterialShell.homeModules.dankMaterialShell.niri
|
||||
./conf/alacritty.nix
|
||||
];
|
||||
|
||||
programs.niri = {
|
||||
@@ -24,7 +23,7 @@
|
||||
enableSpawn = true;
|
||||
};
|
||||
systemd = {
|
||||
enable = true;
|
||||
# enable = true;
|
||||
restartIfChanged = true;
|
||||
};
|
||||
};
|
||||
@@ -38,7 +37,7 @@
|
||||
xdg.enable = true;
|
||||
|
||||
home.packages = [
|
||||
pkgs.alacritty
|
||||
pkgs.kitty
|
||||
pkgs.lite-xl
|
||||
];
|
||||
|
||||
@@ -47,6 +46,10 @@
|
||||
XDG_SESSION_DESKTOP = "niri";
|
||||
};
|
||||
|
||||
xdg.configFile."kitty" = {
|
||||
source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/niri/hm/kitty";
|
||||
recursive = true;
|
||||
};
|
||||
# programs.zsh.enable = false;
|
||||
# programs.fish.enable = true;
|
||||
}
|
||||
|
||||
24
hm/kitty/dank-tabs.conf
Normal file
24
hm/kitty/dank-tabs.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
tab_bar_edge top
|
||||
tab_bar_style powerline
|
||||
tab_powerline_style slanted
|
||||
tab_bar_align left
|
||||
tab_bar_min_tabs 2
|
||||
tab_bar_margin_width 0.0
|
||||
tab_bar_margin_height 2.5 1.5
|
||||
tab_bar_margin_color #fcf8ff
|
||||
|
||||
tab_bar_background #fcf8ff
|
||||
|
||||
active_tab_foreground #17134a
|
||||
active_tab_background #e3dfff
|
||||
active_tab_font_style bold
|
||||
|
||||
inactive_tab_foreground #47464f
|
||||
inactive_tab_background #fcf8ff
|
||||
inactive_tab_font_style normal
|
||||
|
||||
tab_activity_symbol " ● "
|
||||
tab_numbers_style 1
|
||||
|
||||
tab_title_template "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title[:30]}{title[30:] and '…'} [{index}]"
|
||||
active_tab_title_template "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title[:30]}{title[30:] and '…'} [{index}]"
|
||||
24
hm/kitty/dank-theme.conf
Normal file
24
hm/kitty/dank-theme.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
cursor #1c1b21
|
||||
cursor_text_color #47464f
|
||||
|
||||
foreground #1c1b21
|
||||
background #fcf8ff
|
||||
selection_foreground #ffffff
|
||||
selection_background #c7c4dc
|
||||
url_color #5b5891
|
||||
color0 #fcf8ff
|
||||
color1 #8c120b
|
||||
color2 #09720c
|
||||
color3 #7f7a11
|
||||
color4 #6054ff
|
||||
color5 #29247b
|
||||
color6 #5b5891
|
||||
color7 #1a1a1a
|
||||
color8 #2e2e2e
|
||||
color9 #a52720
|
||||
color10 #138c17
|
||||
color11 #999321
|
||||
color12 #6662ad
|
||||
color13 #3f56ff
|
||||
color14 #b259ff
|
||||
color15 #1a1a1a
|
||||
40
hm/kitty/kitty.conf
Normal file
40
hm/kitty/kitty.conf
Normal file
@@ -0,0 +1,40 @@
|
||||
# Font
|
||||
font_family JetBrains Mono Nerd Font
|
||||
font_size 11.0
|
||||
|
||||
# Cursor
|
||||
cursor_shape beam
|
||||
cursor_trail 1
|
||||
|
||||
# Padding (why weird value? consistency with foot)
|
||||
window_margin_width 21.75
|
||||
|
||||
# No stupid close confirmation
|
||||
confirm_os_window_close 0
|
||||
|
||||
# Use fish shell
|
||||
shell fish
|
||||
|
||||
# Copy
|
||||
map ctrl+c copy_or_interrupt
|
||||
|
||||
# Search
|
||||
# map ctrl+f launch --location=hsplit --allow-remote-control kitty +kitten search.py @active-kitty-window-id
|
||||
# map kitty_mod+f launch --location=hsplit --allow-remote-control kitty +kitten search.py @active-kitty-window-id
|
||||
|
||||
# Scroll & Zoom
|
||||
map page_up scroll_page_up
|
||||
map page_down scroll_page_down
|
||||
|
||||
map ctrl+plus change_font_size all +1
|
||||
map ctrl+equal change_font_size all +1
|
||||
map ctrl+kp_add change_font_size all +1
|
||||
map ctrl+minus change_font_size all -1
|
||||
map ctrl+underscore change_font_size all -1
|
||||
map ctrl+kp_subtract change_font_size all -1
|
||||
map ctrl+0 change_font_size all 0
|
||||
map ctrl+kp_0 change_font_size all 0
|
||||
|
||||
# Dank color generation
|
||||
include dank-tabs.conf
|
||||
include dank-theme.conf
|
||||
18
hm/kitty/scroll_mark.py
Normal file
18
hm/kitty/scroll_mark.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from kittens.tui.handler import result_handler
|
||||
from kitty.boss import Boss
|
||||
|
||||
|
||||
def main(args: list[str]) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@result_handler(no_ui=True)
|
||||
def handle_result(
|
||||
args: list[str], answer: str, target_window_id: int, boss: Boss
|
||||
) -> None:
|
||||
w = boss.window_id_map.get(target_window_id)
|
||||
if w is not None:
|
||||
if len(args) > 1 and args[1] != "prev":
|
||||
w.scroll_to_mark(prev=False)
|
||||
else:
|
||||
w.scroll_to_mark()
|
||||
341
hm/kitty/search.py
Normal file
341
hm/kitty/search.py
Normal file
@@ -0,0 +1,341 @@
|
||||
# Kitty search from https://github.com/trygveaa/kitty-kitten-search
|
||||
# License: GPLv3
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
from gettext import gettext as _
|
||||
from pathlib import Path
|
||||
from subprocess import PIPE, run
|
||||
|
||||
from kittens.tui.handler import Handler
|
||||
from kittens.tui.line_edit import LineEdit
|
||||
from kittens.tui.loop import Loop
|
||||
from kittens.tui.operations import (
|
||||
clear_screen,
|
||||
cursor,
|
||||
set_line_wrapping,
|
||||
set_window_title,
|
||||
styled,
|
||||
)
|
||||
from kitty.config import cached_values_for
|
||||
from kitty.key_encoding import EventType
|
||||
from kitty.typing_compat import KeyEventType, ScreenSize
|
||||
|
||||
NON_SPACE_PATTERN = re.compile(r"\S+")
|
||||
SPACE_PATTERN = re.compile(r"\s+")
|
||||
SPACE_PATTERN_END = re.compile(r"\s+$")
|
||||
SPACE_PATTERN_START = re.compile(r"^\s+")
|
||||
|
||||
NON_ALPHANUM_PATTERN = re.compile(r"[^\w\d]+")
|
||||
NON_ALPHANUM_PATTERN_END = re.compile(r"[^\w\d]+$")
|
||||
NON_ALPHANUM_PATTERN_START = re.compile(r"^[^\w\d]+")
|
||||
ALPHANUM_PATTERN = re.compile(r"[\w\d]+")
|
||||
|
||||
|
||||
def call_remote_control(args: list[str]) -> None:
|
||||
subprocess.run(["kitty", "@", *args], capture_output=True)
|
||||
|
||||
|
||||
def reindex(
|
||||
text: str, pattern: re.Pattern[str], right: bool = False
|
||||
) -> tuple[int, int]:
|
||||
if not right:
|
||||
m = pattern.search(text)
|
||||
else:
|
||||
matches = [x for x in pattern.finditer(text) if x]
|
||||
if not matches:
|
||||
raise ValueError
|
||||
m = matches[-1]
|
||||
|
||||
if not m:
|
||||
raise ValueError
|
||||
|
||||
return m.span()
|
||||
|
||||
|
||||
SCROLLMARK_FILE = Path(__file__).parent.absolute() / "scroll_mark.py"
|
||||
|
||||
|
||||
class Search(Handler):
|
||||
def __init__(
|
||||
self, cached_values: dict[str, str], window_ids: list[int], error: str = ""
|
||||
) -> None:
|
||||
self.cached_values = cached_values
|
||||
self.window_ids = window_ids
|
||||
self.error = error
|
||||
self.line_edit = LineEdit()
|
||||
last_search = cached_values.get("last_search", "")
|
||||
self.line_edit.add_text(last_search)
|
||||
self.text_marked = bool(last_search)
|
||||
self.mode = cached_values.get("mode", "text")
|
||||
self.update_prompt()
|
||||
self.mark()
|
||||
|
||||
def update_prompt(self) -> None:
|
||||
self.prompt = "~> " if self.mode == "regex" else "=> "
|
||||
|
||||
def init_terminal_state(self) -> None:
|
||||
self.write(set_line_wrapping(False))
|
||||
self.write(set_window_title(_("Search")))
|
||||
|
||||
def initialize(self) -> None:
|
||||
self.init_terminal_state()
|
||||
self.draw_screen()
|
||||
|
||||
def draw_screen(self) -> None:
|
||||
self.write(clear_screen())
|
||||
if self.window_ids:
|
||||
input_text = self.line_edit.current_input
|
||||
if self.text_marked:
|
||||
self.line_edit.current_input = styled(input_text, reverse=True)
|
||||
self.line_edit.write(self.write, self.prompt)
|
||||
self.line_edit.current_input = input_text
|
||||
if self.error:
|
||||
with cursor(self.write):
|
||||
self.print("")
|
||||
for l in self.error.split("\n"):
|
||||
self.print(l)
|
||||
|
||||
def refresh(self) -> None:
|
||||
self.draw_screen()
|
||||
self.mark()
|
||||
|
||||
def switch_mode(self) -> None:
|
||||
if self.mode == "regex":
|
||||
self.mode = "text"
|
||||
else:
|
||||
self.mode = "regex"
|
||||
self.cached_values["mode"] = self.mode
|
||||
self.update_prompt()
|
||||
|
||||
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
|
||||
if self.text_marked:
|
||||
self.text_marked = False
|
||||
self.line_edit.clear()
|
||||
self.line_edit.on_text(text, in_bracketed_paste)
|
||||
self.refresh()
|
||||
|
||||
def on_key(self, key_event: KeyEventType) -> None:
|
||||
if (
|
||||
self.text_marked
|
||||
and key_event.type == EventType.PRESS
|
||||
and key_event.key
|
||||
not in [
|
||||
"TAB",
|
||||
"LEFT_CONTROL",
|
||||
"RIGHT_CONTROL",
|
||||
"LEFT_ALT",
|
||||
"RIGHT_ALT",
|
||||
"LEFT_SHIFT",
|
||||
"RIGHT_SHIFT",
|
||||
"LEFT_SUPER",
|
||||
"RIGHT_SUPER",
|
||||
]
|
||||
):
|
||||
self.text_marked = False
|
||||
self.refresh()
|
||||
|
||||
if self.line_edit.on_key(key_event):
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
if key_event.matches("ctrl+u"):
|
||||
self.line_edit.clear()
|
||||
self.refresh()
|
||||
elif key_event.matches("ctrl+a"):
|
||||
self.line_edit.home()
|
||||
self.refresh()
|
||||
elif key_event.matches("ctrl+e"):
|
||||
self.line_edit.end()
|
||||
self.refresh()
|
||||
elif key_event.matches("ctrl+backspace") or key_event.matches("ctrl+w"):
|
||||
before, _ = self.line_edit.split_at_cursor()
|
||||
|
||||
try:
|
||||
start, _ = reindex(before, SPACE_PATTERN_END, right=True)
|
||||
except ValueError:
|
||||
start = -1
|
||||
|
||||
try:
|
||||
space = before[:start].rindex(" ")
|
||||
except ValueError:
|
||||
space = 0
|
||||
self.line_edit.backspace(len(before) - space)
|
||||
self.refresh()
|
||||
elif key_event.matches("ctrl+left") or key_event.matches("ctrl+b"):
|
||||
before, _ = self.line_edit.split_at_cursor()
|
||||
try:
|
||||
start, _ = reindex(before, SPACE_PATTERN_END, right=True)
|
||||
except ValueError:
|
||||
start = -1
|
||||
|
||||
try:
|
||||
space = before[:start].rindex(" ")
|
||||
except ValueError:
|
||||
space = 0
|
||||
self.line_edit.left(len(before) - space)
|
||||
self.refresh()
|
||||
elif key_event.matches("ctrl+right") or key_event.matches("ctrl+f"):
|
||||
_, after = self.line_edit.split_at_cursor()
|
||||
try:
|
||||
_, end = reindex(after, SPACE_PATTERN_START)
|
||||
except ValueError:
|
||||
end = 0
|
||||
|
||||
try:
|
||||
space = after[end:].index(" ") + 1
|
||||
except ValueError:
|
||||
space = len(after)
|
||||
self.line_edit.right(space)
|
||||
self.refresh()
|
||||
elif key_event.matches("alt+backspace") or key_event.matches("alt+w"):
|
||||
before, _ = self.line_edit.split_at_cursor()
|
||||
|
||||
try:
|
||||
start, _ = reindex(before, NON_ALPHANUM_PATTERN_END, right=True)
|
||||
except ValueError:
|
||||
start = -1
|
||||
else:
|
||||
self.line_edit.backspace(len(before) - start)
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
try:
|
||||
start, _ = reindex(before, NON_ALPHANUM_PATTERN, right=True)
|
||||
except ValueError:
|
||||
self.line_edit.backspace(len(before))
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
self.line_edit.backspace(len(before) - (start + 1))
|
||||
self.refresh()
|
||||
elif key_event.matches("alt+left") or key_event.matches("alt+b"):
|
||||
before, _ = self.line_edit.split_at_cursor()
|
||||
|
||||
try:
|
||||
start, _ = reindex(before, NON_ALPHANUM_PATTERN_END, right=True)
|
||||
except ValueError:
|
||||
start = -1
|
||||
else:
|
||||
self.line_edit.left(len(before) - start)
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
try:
|
||||
start, _ = reindex(before, NON_ALPHANUM_PATTERN, right=True)
|
||||
except ValueError:
|
||||
self.line_edit.left(len(before))
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
self.line_edit.left(len(before) - (start + 1))
|
||||
self.refresh()
|
||||
elif key_event.matches("alt+right") or key_event.matches("alt+f"):
|
||||
_, after = self.line_edit.split_at_cursor()
|
||||
|
||||
try:
|
||||
_, end = reindex(after, NON_ALPHANUM_PATTERN_START)
|
||||
except ValueError:
|
||||
end = 0
|
||||
else:
|
||||
self.line_edit.right(end)
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
try:
|
||||
_, end = reindex(after, NON_ALPHANUM_PATTERN)
|
||||
except ValueError:
|
||||
self.line_edit.right(len(after))
|
||||
self.refresh()
|
||||
return
|
||||
|
||||
self.line_edit.right(end - 1)
|
||||
self.refresh()
|
||||
elif key_event.matches("tab"):
|
||||
self.switch_mode()
|
||||
self.refresh()
|
||||
elif key_event.matches("up") or key_event.matches("f3"):
|
||||
for match_arg in self.match_args():
|
||||
call_remote_control(["kitten", match_arg, str(SCROLLMARK_FILE)])
|
||||
elif key_event.matches("down") or key_event.matches("shift+f3"):
|
||||
for match_arg in self.match_args():
|
||||
call_remote_control(["kitten", match_arg, str(SCROLLMARK_FILE), "next"])
|
||||
elif key_event.matches("enter"):
|
||||
self.quit(0)
|
||||
elif key_event.matches("esc"):
|
||||
self.quit(1)
|
||||
|
||||
def on_interrupt(self) -> None:
|
||||
self.quit(1)
|
||||
|
||||
def on_eot(self) -> None:
|
||||
self.quit(1)
|
||||
|
||||
def on_resize(self, screen_size: ScreenSize) -> None:
|
||||
self.refresh()
|
||||
|
||||
def match_args(self) -> list[str]:
|
||||
return [f"--match=id:{window_id}" for window_id in self.window_ids]
|
||||
|
||||
def mark(self) -> None:
|
||||
if not self.window_ids:
|
||||
return
|
||||
text = self.line_edit.current_input
|
||||
if text:
|
||||
match_case = "i" if text.islower() else ""
|
||||
match_type = match_case + self.mode
|
||||
for match_arg in self.match_args():
|
||||
try:
|
||||
call_remote_control(
|
||||
["create-marker", match_arg, match_type, "1", text]
|
||||
)
|
||||
except SystemExit:
|
||||
self.remove_mark()
|
||||
else:
|
||||
self.remove_mark()
|
||||
|
||||
def remove_mark(self) -> None:
|
||||
for match_arg in self.match_args():
|
||||
call_remote_control(["remove-marker", match_arg])
|
||||
|
||||
def quit(self, return_code: int) -> None:
|
||||
self.cached_values["last_search"] = self.line_edit.current_input
|
||||
self.remove_mark()
|
||||
if return_code:
|
||||
for match_arg in self.match_args():
|
||||
call_remote_control(["scroll-window", match_arg, "end"])
|
||||
self.quit_loop(return_code)
|
||||
|
||||
|
||||
def main(args: list[str]) -> None:
|
||||
call_remote_control(
|
||||
["resize-window", "--self", "--axis=vertical", "--increment", "-100"]
|
||||
)
|
||||
|
||||
error = ""
|
||||
if len(args) < 2 or not args[1].isdigit():
|
||||
error = "Error: Window id must be provided as the first argument."
|
||||
|
||||
window_id = int(args[1])
|
||||
window_ids = [window_id]
|
||||
if len(args) > 2 and args[2] == "--all-windows":
|
||||
ls_output = run(["kitty", "@", "ls"], stdout=PIPE)
|
||||
ls_json = json.loads(ls_output.stdout.decode())
|
||||
current_tab = None
|
||||
for os_window in ls_json:
|
||||
for tab in os_window["tabs"]:
|
||||
for kitty_window in tab["windows"]:
|
||||
if kitty_window["id"] == window_id:
|
||||
current_tab = tab
|
||||
if current_tab:
|
||||
window_ids = [
|
||||
w["id"] for w in current_tab["windows"] if not w["is_focused"]
|
||||
]
|
||||
else:
|
||||
error = "Error: Could not find the window id provided."
|
||||
|
||||
loop = Loop()
|
||||
with cached_values_for("search") as cached_values:
|
||||
handler = Search(cached_values, window_ids, error)
|
||||
loop.loop(handler)
|
||||
Reference in New Issue
Block a user