diff options
-rw-r--r-- | dot-config/fish/config.fish | 19 | ||||
-rw-r--r-- | dot-config/ghostty/config | 44 | ||||
-rw-r--r-- | dot-config/git/config | 7 | ||||
-rw-r--r-- | dot-config/hypr/hyprlock.conf | 19 | ||||
-rw-r--r-- | dot-config/mako/config | 31 | ||||
-rw-r--r-- | dot-config/niri/config.kdl | 595 | ||||
-rw-r--r-- | dot-config/nvim/init.lua | 444 | ||||
-rw-r--r-- | dot-config/nvim/lazy-lock.json | 23 | ||||
-rw-r--r-- | dot-config/systemd/user/yubikey-agent.service.d/override.conf | 3 | ||||
-rw-r--r-- | dot-config/waybar/config.jsonc | 171 | ||||
-rw-r--r-- | dot-config/waybar/style.css | 193 | ||||
-rwxr-xr-x | dot-local-bin/brightness | 7 | ||||
-rwxr-xr-x | dot-local-bin/dark-light-switch | 7 | ||||
-rwxr-xr-x | dot-local-bin/wp-vol | 8 | ||||
-rw-r--r-- | etc/ssh/ssh_config.d/my.conf | 4 | ||||
-rwxr-xr-x | init | 29 |
16 files changed, 1604 insertions, 0 deletions
diff --git a/dot-config/fish/config.fish b/dot-config/fish/config.fish new file mode 100644 index 0000000..849276c --- /dev/null +++ b/dot-config/fish/config.fish @@ -0,0 +1,19 @@ +if status is-interactive + [ (tty) = /dev/tty1 ] && exec niri-session +end + +function fish_greeting +end + +fish_add_path "$HOME/.local/bin" + +alias e nvim +alias lg lazygit + +set -x SSH_AUTH_SOCK "$XDG_RUNTIME_DIR/yubikey-agent/yubikey-agent.sock" + +set -x VISUAL nvim +set -x EDITOR nvim + +set -x GOPATH "$HOME/.local/share/go" +fish_add_path "$GOPATH/bin" diff --git a/dot-config/ghostty/config b/dot-config/ghostty/config new file mode 100644 index 0000000..9b3cdae --- /dev/null +++ b/dot-config/ghostty/config @@ -0,0 +1,44 @@ +# This is the configuration file for Ghostty. +# +# This template file has been automatically created at the following +# path since Ghostty couldn't find any existing config files on your system: +# +# /home/mathias/.config/ghostty/config +# +# The template does not set any default options, since Ghostty ships +# with sensible defaults for all options. Users should only need to set +# options that they want to change from the default. +# +# Run `ghostty +show-config --default --docs` to view a list of +# all available config options and their default values. +# +# Additionally, each config option is also explained in detail +# on Ghostty's website, at https://ghostty.org/docs/config. + +# Config syntax crash course +# ========================== +# # The config file consists of simple key-value pairs, +# # separated by equals signs. +# font-family = Iosevka +# window-padding-x = 2 +# +# # Spacing around the equals sign does not matter. +# # All of these are identical: +# key=value +# key= value +# key =value +# key = value +# +# # Any line beginning with a # is a comment. It's not possible to put +# # a comment after a config option, since it would be interpreted as a +# # part of the value. For example, this will have a value of "#123abc": +# background = #123abc +# +# # Empty values are used to reset config keys to default. +# key = +# +# # Some config options have unique syntaxes for their value, +# # which is explained in the docs for that config option. +# # Just for example: +# resize-overlay-duration = 4s 200ms +theme = dark:catppuccin-mocha,light:catppuccin-latte diff --git a/dot-config/git/config b/dot-config/git/config new file mode 100644 index 0000000..7a16e2f --- /dev/null +++ b/dot-config/git/config @@ -0,0 +1,7 @@ +[init] + defaultBranch = master +[merge] + conflictStyle = diff3 +[user] + email = mathias@magnusson.space + name = Mathias Magnusson diff --git a/dot-config/hypr/hyprlock.conf b/dot-config/hypr/hyprlock.conf new file mode 100644 index 0000000..df135e6 --- /dev/null +++ b/dot-config/hypr/hyprlock.conf @@ -0,0 +1,19 @@ +background { + path = screenshot + blur_passes = 2 + blur_size = 3 + brightness = 1 + noise = 0.07 +} + +input-field { + size = 20%, 5% + outer_color = rgba(0, 0, 0, 0) + inner_color = rgba(0, 0, 0, 0) + font_color = rgb(128, 128, 128) + check_color = rgba(0, 0, 0, 0) + placeholder = "" + position = 0, -20 + halign = center + valign = center +} diff --git a/dot-config/mako/config b/dot-config/mako/config new file mode 100644 index 0000000..c0cb2ff --- /dev/null +++ b/dot-config/mako/config @@ -0,0 +1,31 @@ +default-timeout=5000 + +[app-name=wp-vol] +layer=overlay +history=0 +anchor=bottom-center +group-by=app-name +format=<b>%s</b>\n%b +background-color=#282828 +progress-color=#383838 +text-color=#eadab1 +border-color=#eadab1 +border-size=1 +border-radius=4 +text-alignment=center +outer-margin=40 + +[app-name=brightness] +layer=overlay +history=0 +anchor=bottom-center +group-by=app-name +format=<b>%s</b>\n%b +background-color=#282828 +progress-color=#383838 +text-color=#eadab1 +border-color=#eadab1 +border-size=1 +border-radius=4 +text-alignment=center +outer-margin=40 diff --git a/dot-config/niri/config.kdl b/dot-config/niri/config.kdl new file mode 100644 index 0000000..908a575 --- /dev/null +++ b/dot-config/niri/config.kdl @@ -0,0 +1,595 @@ +// This config is in the KDL format: https://kdl.dev +// "/-" comments out the following node. +// Check the wiki for a full description of the configuration: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Introduction + +// Input device configuration. +// Find the full list of options on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Input +input { + keyboard { + xkb { + // You can set rules, model, layout, variant and options. + // For more information, see xkeyboard-config(7). + + // For example: + // layout "us,ru" + // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps" + layout "us" + variant "colemak_dh" + options "caps:escape" + } + + // Enable numlock on startup, omitting this setting disables it. + numlock + } + + // Next sections include libinput settings. + // Omitting settings disables them, or leaves them at their default values. + touchpad { + // off + tap + // dwt + // dwtp + // drag false + // drag-lock + natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "two-finger" + // disabled-on-external-mouse + click-method "clickfinger" + } + + mouse { + // off + // natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "no-scroll" + } + + trackpoint { + // off + // natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "on-button-down" + // scroll-button 273 + // middle-emulation + } + + // Uncomment this to make the mouse warp to the center of newly focused windows. + // warp-mouse-to-focus + + // Focus windows and outputs automatically when moving the mouse into them. + // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen. + // focus-follows-mouse max-scroll-amount="0%" +} + +// You can configure outputs by their name, which you can find +// by running `niri msg outputs` while inside a niri instance. +// The built-in laptop monitor is usually called "eDP-1". +// Find more information on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Outputs +// Remember to uncomment the node by removing "/-"! +output "eDP-1" { + // Uncomment this line to disable this output. + // off + + // Resolution and, optionally, refresh rate of the output. + // The format is "<width>x<height>" or "<width>x<height>@<refresh rate>". + // If the refresh rate is omitted, niri will pick the highest refresh rate + // for the resolution. + // If the mode is omitted altogether or is invalid, niri will pick one automatically. + // Run `niri msg outputs` while inside a niri instance to list all outputs and their modes. + mode "1920x1080@60.008" + + // You can use integer or fractional scale, for example use 1.5 for 150% scale. + scale 1 + + // Transform allows to rotate the output counter-clockwise, valid values are: + // normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270. + transform "normal" + + // Position of the output in the global coordinate space. + // This affects directional monitor actions like "focus-monitor-left", and cursor movement. + // The cursor can only move between directly adjacent outputs. + // Output scale and rotation has to be taken into account for positioning: + // outputs are sized in logical, or scaled, pixels. + // For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080, + // so to put another output directly adjacent to it on the right, set its x to 1920. + // If the position is unset or results in an overlap, the output is instead placed + // automatically. + position x=0 y=0 +} + +output "DP-1" { + mode "1920x1080@60.000" + scale 1 + position x=1920 y=0 +} + +// Settings that influence how windows are positioned and sized. +// Find more information on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout +layout { + // Set gaps around windows in logical pixels. + gaps 16 + + // When to center a column when changing focus, options are: + // - "never", default behavior, focusing an off-screen column will keep at the left + // or right edge of the screen. + // - "always", the focused column will always be centered. + // - "on-overflow", focusing a column will center it if it doesn't fit + // together with the previously focused column. + center-focused-column "never" + + // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between. + preset-column-widths { + // Proportion sets the width as a fraction of the output width, taking gaps into account. + // For example, you can perfectly fit four windows sized "proportion 0.25" on an output. + // The default preset widths are 1/3, 1/2 and 2/3 of the output. + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + + // Fixed sets the width in logical pixels exactly. + // fixed 1920 + } + + // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between. + // preset-window-heights { } + + // You can change the default width of the new windows. + default-column-width { proportion 0.5; } + // If you leave the brackets empty, the windows themselves will decide their initial width. + // default-column-width {} + + // By default focus ring and border are rendered as a solid background rectangle + // behind windows. That is, they will show up through semitransparent windows. + // This is because windows using client-side decorations can have an arbitrary shape. + // + // If you don't like that, you should uncomment `prefer-no-csd` below. + // Niri will draw focus ring and border *around* windows that agree to omit their + // client-side decorations. + // + // Alternatively, you can override it with a window rule called + // `draw-border-with-background`. + + // You can change how the focus ring looks. + focus-ring { + // Uncomment this line to disable the focus ring. + // off + + // How many logical pixels the ring extends out from the windows. + width 1 + + // Colors can be set in a variety of ways: + // - CSS named colors: "red" + // - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" + // - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others. + + // Color of the ring on the active monitor. + active-color "#e8d8af" + + // Color of the ring on inactive monitors. + inactive-color "#505050" + + // You can also use gradients. They take precedence over solid colors. + // Gradients are rendered the same as CSS linear-gradient(angle, from, to). + // The angle is the same as in linear-gradient, and is optional, + // defaulting to 180 (top-to-bottom gradient). + // You can use any CSS linear-gradient tool on the web to set these up. + // Changing the color space is also supported, check the wiki for more info. + // + // active-gradient from="#80c8ff" to="#bbddff" angle=45 + + // You can also color the gradient relative to the entire view + // of the workspace, rather than relative to just the window itself. + // To do that, set relative-to="workspace-view". + // + // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" + } + + // You can also add a border. It's similar to the focus ring, but always visible. + border { + // The settings are the same as for the focus ring. + // If you enable the border, you probably want to disable the focus ring. + off + + width 4 + active-color "#ffc87f" + inactive-color "#505050" + + // Color of the border around windows that request your attention. + urgent-color "#9b0000" + + // active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view" + // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" + } + + // You can enable drop shadows for windows. + shadow { + // Uncomment the next line to enable shadows. + on + + // By default, the shadow draws only around its window, and not behind it. + // Uncomment this setting to make the shadow draw behind its window. + // + // Note that niri has no way of knowing about the CSD window corner + // radius. It has to assume that windows have square corners, leading to + // shadow artifacts inside the CSD rounded corners. This setting fixes + // those artifacts. + // + // However, instead you may want to set prefer-no-csd and/or + // geometry-corner-radius. Then, niri will know the corner radius and + // draw the shadow correctly, without having to draw it behind the + // window. These will also remove client-side shadows if the window + // draws any. + // + // draw-behind-window true + + // You can change how shadows look. The values below are in logical + // pixels and match the CSS box-shadow properties. + + // Softness controls the shadow blur radius. + softness 15 + + // Spread expands the shadow. + spread 0 + + // Offset moves the shadow relative to the window. + offset x=3 y=5 + + // You can also change the shadow color and opacity. + color "#0007" + } + + // Struts shrink the area occupied by windows, similarly to layer-shell panels. + // You can think of them as a kind of outer gaps. They are set in logical pixels. + // Left and right struts will cause the next window to the side to always be visible. + // Top and bottom struts will simply add outer gaps in addition to the area occupied by + // layer-shell panels and regular gaps. + struts { + // left 64 + // right 64 + // top 64 + // bottom 64 + } + + background-color "transparent" +} + +// Add lines like this to spawn processes at startup. +// Note that running niri as a session supports xdg-desktop-autostart, +// which may be more convenient to use. +// See the binds section below for more spawn examples. + +// This line starts waybar, a commonly used bar for Wayland compositors. +spawn-at-startup "waybar" + +spawn-at-startup "xwayland-satellite" +environment { + DISPLAY ":0" +} + +spawn-at-startup "hyprlock" + +spawn-at-startup "swaybg" "-i" "/home/mathias/.local/share/wallpapers/winter.jpg" + +layer-rule { + match namespace="^wallpaper$" + place-within-backdrop true +} + +// Uncomment this line to ask the clients to omit their client-side decorations if possible. +// If the client will specifically ask for CSD, the request will be honored. +// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners. +// This option will also fix border/focus ring drawing behind some semitransparent windows. +// After enabling or disabling this, you need to restart the apps for this to take effect. +// prefer-no-csd + +// You can change the path where screenshots are saved. +// A ~ at the front will be expanded to the home directory. +// The path is formatted with strftime(3) to give you the screenshot date and time. +screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" + +// You can also set this to null to disable saving screenshots to disk. +// screenshot-path null + +// Animation settings. +// The wiki explains how to configure individual animations: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Animations +animations { + // Uncomment to turn off all animations. + // off + + // Slow down all animations by this factor. Values below 1 speed them up instead. + // slowdown 3.0 +} + +// Window rules let you adjust behavior for individual windows. +// Find more information on the wiki: +// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules + +// Open the Firefox picture-in-picture player as floating by default. +window-rule { + // This app-id regular expression will work for both: + // - host Firefox (app-id is "firefox") + // - Flatpak Firefox (app-id is "org.mozilla.firefox") + match app-id=r#"firefox$"# title="^Picture-in-Picture$" + open-floating true +} + +// Example: block out two password managers from screen capture. +// (This example rule is commented out with a "/-" in front.) +/-window-rule { + match app-id=r#"^org\.keepassxc\.KeePassXC$"# + match app-id=r#"^org\.gnome\.World\.Secrets$"# + + block-out-from "screen-capture" + + // Use this instead if you want them visible on third-party screenshot tools. + // block-out-from "screencast" +} + +// Example: enable rounded corners for all windows. +// (This example rule is commented out with a "/-" in front.) +window-rule { + geometry-corner-radius 12 + clip-to-geometry true +} + +window-rule { + match app-id="pinentry-gtk" + open-floating true + block-out-from "screen-capture" +} + +hotkey-overlay { + skip-at-startup +} + +binds { + // Keys consist of modifiers separated by + signs, followed by an XKB key name + // in the end. To find an XKB name for a particular key, you may use a program + // like wev. + // + // "Mod" is a special modifier equal to Super when running on a TTY, and to Alt + // when running as a winit window. + // + // Most actions that you can bind here can also be invoked programmatically with + // `niri msg action do-something`. + + // Mod-Shift-/, which is usually the same as Mod-?, + // shows a list of important hotkeys. + Mod+Shift+Slash { show-hotkey-overlay; } + + // Suggested binds for running programs: terminal, app launcher, screen locker. + Mod+Return hotkey-overlay-title="Open a Terminal: ghostty" { spawn "ghostty" "--gtk-single-instance=true"; } + Mod+Slash hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; } + Super+Escape hotkey-overlay-title="Lock the Screen: swaylock" { spawn "hyprlock"; } + + Mod+S hotkey-overlay-title="Set dynamic cast window" { spawn "fish" "-c" "niri msg action set-dynamic-cast-window --id (niri msg --json pick-window | jq .id)"; } + + // You can also use a shell. Do this if you need pipes, multiple commands, etc. + // Note: the entire command goes as a single argument in the end. + // Mod+T { spawn "bash" "-c" "notify-send hello && exec alacritty"; } + + // Example volume keys mappings for PipeWire & WirePlumber. + // The allow-when-locked=true property makes them work even when the session is locked. + XF86AudioRaiseVolume allow-when-locked=true { spawn "wp-vol" "0.05+"; } + XF86AudioLowerVolume allow-when-locked=true { spawn "wp-vol" "0.05-"; } + XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; } + + XF86AudioPlay allow-when-locked=true { spawn "playerctl" "play-pause"; } + XF86AudioPrev allow-when-locked=true { spawn "playerctl" "previous"; } + XF86AudioNext allow-when-locked=true { spawn "playerctl" "next"; } + + XF86MonBrightnessUp allow-when-locked=true { spawn "brightness" "1+"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "brightness" "1-"; } + + // Open/close the Overview: a zoomed-out view of workspaces and windows. + // You can also move the mouse into the top-left hot corner, + // or do a four-finger swipe up on a touchpad. + Mod+O repeat=false { toggle-overview; } + + Mod+D { spawn "dark-light-switch"; } + + Mod+Q { close-window; } + + Mod+N { focus-column-left; } + Mod+H { focus-window-down; } + Mod+L { focus-window-up; } + Mod+E { focus-column-right; } + + Mod+Shift+N { move-column-left; } + Mod+Shift+H { move-window-down; } + Mod+Shift+L { move-window-up; } + Mod+Shift+E { move-column-right; } + + // Alternative commands that move across workspaces when reaching + // the first or last window in a column. + // Mod+J { focus-window-or-workspace-down; } + // Mod+K { focus-window-or-workspace-up; } + // Mod+Ctrl+J { move-window-down-or-to-workspace-down; } + // Mod+Ctrl+K { move-window-up-or-to-workspace-up; } + + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + Mod+Ctrl+N { focus-monitor-left; } + Mod+Ctrl+H { focus-monitor-down; } + Mod+Ctrl+L { focus-monitor-up; } + Mod+Ctrl+E { focus-monitor-right; } + + Mod+Shift+Ctrl+N { move-column-to-monitor-left; } + Mod+Shift+Ctrl+H { move-column-to-monitor-down; } + Mod+Shift+Ctrl+L { move-column-to-monitor-up; } + Mod+Shift+Ctrl+E { move-column-to-monitor-right; } + + // Alternatively, there are commands to move just a single window: + // Mod+Shift+Ctrl+Left { move-window-to-monitor-left; } + // ... + + // And you can also move a whole workspace to another monitor: + // Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; } + // ... + + Mod+U { focus-workspace-down; } + Mod+Y { focus-workspace-up; } + Mod+Ctrl+U { move-column-to-workspace-down; } + Mod+Ctrl+Y { move-column-to-workspace-up; } + + // Mod+Shift+U { move-workspace-down; } + // Mod+Shift+Y { move-workspace-up; } + + // You can bind mouse wheel scroll ticks using the following syntax. + // These binds will change direction based on the natural-scroll setting. + // + // To avoid scrolling through workspaces really fast, you can use + // the cooldown-ms property. The bind will be rate-limited to this value. + // You can set a cooldown on any bind, but it's most useful for the wheel. + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; } + + Mod+WheelScrollRight { focus-column-right; } + Mod+WheelScrollLeft { focus-column-left; } + Mod+Ctrl+WheelScrollRight { move-column-right; } + Mod+Ctrl+WheelScrollLeft { move-column-left; } + + // Usually scrolling up and down with Shift in applications results in + // horizontal scrolling; these binds replicate that. + Mod+Shift+WheelScrollDown { focus-column-right; } + Mod+Shift+WheelScrollUp { focus-column-left; } + Mod+Ctrl+Shift+WheelScrollDown { move-column-right; } + Mod+Ctrl+Shift+WheelScrollUp { move-column-left; } + + // Similarly, you can bind touchpad scroll "ticks". + // Touchpad scrolling is continuous, so for these binds it is split into + // discrete intervals. + // These binds are also affected by touchpad's natural-scroll, so these + // example binds are "inverted", since we have natural-scroll enabled for + // touchpads by default. + // Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; } + // Mod+TouchpadScrollUp { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; } + + // You can refer to workspaces by index. However, keep in mind that + // niri is a dynamic workspace system, so these commands are kind of + // "best effort". Trying to refer to a workspace index bigger than + // the current workspace count will instead refer to the bottommost + // (empty) workspace. + // + // For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on + // will all refer to the 3rd workspace. + Mod+1 { focus-workspace 1; } + Mod+2 { focus-workspace 2; } + Mod+3 { focus-workspace 3; } + Mod+4 { focus-workspace 4; } + Mod+5 { focus-workspace 5; } + Mod+6 { focus-workspace 6; } + Mod+7 { focus-workspace 7; } + Mod+8 { focus-workspace 8; } + Mod+9 { focus-workspace 9; } + Mod+Ctrl+1 { move-column-to-workspace 1; } + Mod+Ctrl+2 { move-column-to-workspace 2; } + Mod+Ctrl+3 { move-column-to-workspace 3; } + Mod+Ctrl+4 { move-column-to-workspace 4; } + Mod+Ctrl+5 { move-column-to-workspace 5; } + Mod+Ctrl+6 { move-column-to-workspace 6; } + Mod+Ctrl+7 { move-column-to-workspace 7; } + Mod+Ctrl+8 { move-column-to-workspace 8; } + Mod+Ctrl+9 { move-column-to-workspace 9; } + + // Alternatively, there are commands to move just a single window: + // Mod+Ctrl+1 { move-window-to-workspace 1; } + + // Switches focus between the current and the previous workspace. + // Mod+Tab { focus-workspace-previous; } + + // The following binds move the focused window in and out of a column. + // If the window is alone, they will consume it into the nearby column to the side. + // If the window is already in a column, they will expel it out. + Mod+BracketLeft { consume-or-expel-window-left; } + Mod+BracketRight { consume-or-expel-window-right; } + + // Consume one window from the right to the bottom of the focused column. + Mod+Comma { consume-window-into-column; } + // Expel the bottom window from the focused column to the right. + Mod+Period { expel-window-from-column; } + + Mod+R { switch-preset-column-width; } + Mod+Shift+R { switch-preset-window-height; } + Mod+Ctrl+R { reset-window-height; } + Mod+F { maximize-column; } + Mod+Shift+F { fullscreen-window; } + + // Expand the focused column to space not taken up by other fully visible columns. + // Makes the column "fill the rest of the space". + Mod+Ctrl+F { expand-column-to-available-width; } + + Mod+C { center-column; } + + // Center all fully visible columns on screen. + Mod+Ctrl+C { center-visible-columns; } + + // Finer width adjustments. + // This command can also: + // * set width in pixels: "1000" + // * adjust width in pixels: "-5" or "+5" + // * set width as a percentage of screen width: "25%" + // * adjust width as a percentage of screen width: "-10%" or "+10%" + // Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0, + // set-column-width "100" will make the column occupy 200 physical screen pixels. + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + // Finer height adjustments when in column with other windows. + Mod+Shift+Minus { set-window-height "-10%"; } + Mod+Shift+Equal { set-window-height "+10%"; } + + // Move the focused window between the floating and the tiling layout. + Mod+V { toggle-window-floating; } + Mod+Shift+V { switch-focus-between-floating-and-tiling; } + + // Toggle tabbed column display mode. + // Windows in this column will appear as vertical tabs, + // rather than stacked on top of each other. + Mod+W { toggle-column-tabbed-display; } + + // Actions to switch layouts. + // Note: if you uncomment these, make sure you do NOT have + // a matching layout switch hotkey configured in xkb options above. + // Having both at once on the same hotkey will break the switching, + // since it will switch twice upon pressing the hotkey (once by xkb, once by niri). + // Mod+Space { switch-layout "next"; } + // Mod+Shift+Space { switch-layout "prev"; } + + Print { screenshot; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + + // Applications such as remote-desktop clients and software KVM switches may + // request that niri stops processing the keyboard shortcuts defined here + // so they may, for example, forward the key presses as-is to a remote machine. + // It's a good idea to bind an escape hatch to toggle the inhibitor, + // so a buggy application can't hold your session hostage. + // + // The allow-inhibiting=false property can be applied to other binds as well, + // which ensures niri always processes them, even when an inhibitor is active. + Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; } + + // The quit action will show a confirmation dialog to avoid accidental exits. + Mod+Shift+Q { quit; } + Ctrl+Alt+Delete { quit; } + + // Powers off the monitors. To turn them back on, do any input like + // moving the mouse or pressing any other key. + Mod+Shift+P { power-off-monitors; } +} diff --git a/dot-config/nvim/init.lua b/dot-config/nvim/init.lua new file mode 100644 index 0000000..3f7a2be --- /dev/null +++ b/dot-config/nvim/init.lua @@ -0,0 +1,444 @@ +-- Settings +local set = vim.o + +set.et = true +set.sw = 4 +set.sts = -1 +set.ts = 4 +set.nu = true +set.signcolumn = "yes" +set.updatetime = 1000 +set.ignorecase = true +set.smartcase = true +set.backup = false +set.undodir = vim.fn.stdpath("data") .. "/undodir" +set.undofile = true +set.splitright = true +set.splitbelow = true +set.breakindent = true +set.termguicolors = true +set.linebreak = true + +vim.g.omni_sql_no_default_maps = 1337 +-- vim.g.asmsyntax = "nasm" + +vim.api.nvim_create_autocmd("TermOpen", { + group = vim.api.nvim_create_augroup("TermNoNumbers", {}), + command = "setlocal nonu nornu signcolumn=no" +}) + +vim.api.nvim_create_autocmd("TextYankPost", { + group = vim.api.nvim_create_augroup("HighlightYank", {}), + callback = function() vim.highlight.on_yank() end, +}) + +vim.filetype.add({ + filename = { + ["compose.yaml"] = "yaml.docker-compose", + ["docker-compose.yaml"] = "yaml.docker-compose", + }, + extension = { + templ = "templ", + typ = "typst", + } +}) + +vim.diagnostic.config({ + virtual_text = true, + virtual_lines = { current_line = true }, +}) + +-- Keymaps +for _, mod in ipairs({ + function(x) return x end, + function(x) return "<c-w>" .. x end, + function(x) return "<c-w><c-" .. x .. ">" end, + function(x) return string.upper(x) end, +}) do + vim.keymap.set("", mod("n"), mod("j")) + vim.keymap.set("", mod("e"), mod("k")) + vim.keymap.set("", mod("k"), mod("n")) + vim.keymap.set("", mod("j"), mod("e")) +end + +vim.g.mapleader = " " +vim.keymap.set("n", "gp", vim.cmd.bp) +vim.keymap.set("n", "gn", vim.cmd.bn) +vim.keymap.set("n", "<leader>h", function() set.hls = not set.hls end) +vim.keymap.set("t", "<c-l>", "<c-\\><c-n>") +vim.keymap.set("n", "<space>", "<nop>", { silent = true }) + +local function lsp_maps(buf) + local telescope_builtin = require("telescope.builtin") + local opts = { buffer = buf } + + vim.keymap.set("n", "gd", telescope_builtin.lsp_definitions, opts) + vim.keymap.set("n", "gr", telescope_builtin.lsp_references, opts) + vim.keymap.set("n", "gi", telescope_builtin.lsp_implementations, opts) + vim.keymap.set("n", "gy", telescope_builtin.lsp_type_definitions, opts) + vim.keymap.set("n", "<leader>d", telescope_builtin.diagnostics, opts) + vim.keymap.set("n", "grn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) + vim.keymap.set("n", "<leader>k", vim.diagnostic.open_float, opts) + vim.keymap.set("n", "<leader>K", vim.diagnostic.setqflist, opts) + vim.keymap.set("n", "<leader>e", vim.lsp.buf.hover, opts) + vim.keymap.set("i", "<c-k>", vim.lsp.buf.signature_help, opts) + vim.keymap.set("n", "<leader>.", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "<leader>i", vim.lsp.buf.format, opts) +end + +-- LSP +vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("UserLspConfig", {}), + callback = function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + lsp_maps(ev.buf) + + if client.server_capabilities.documentHighlightProvider then + local bg = require("catppuccin.palettes").get_palette().surface0 + vim.api.nvim_set_hl(0, "LspReferenceText", { bg = bg }) + vim.api.nvim_set_hl(0, "LspReferenceRead", { bg = bg }) + vim.api.nvim_set_hl(0, "LspReferenceWrite", { bg = bg }) + + local group = vim.api.nvim_create_augroup("CursorHoldHighlightReferences", {}) + vim.api.nvim_create_autocmd("CursorHold", { + group = group, + buffer = ev.buf, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd("CursorMoved", { + group = group, + buffer = ev.buf, + callback = vim.lsp.buf.clear_references, + }) + end + end +}) + +local function setup_lsp() + local lsp = require "lspconfig" + local capabilities = require "cmp_nvim_lsp".default_capabilities() + local function mkCap(obj) + if not obj then + obj = {} + end + if not obj.capabilities then + obj.capabilities = capabilities + end + return obj + end + lsp.gopls.setup { + capabilities = capabilities, + settings = { gopls = { + usePlaceholders = true, + semanticTokens = true, + } }, + } + lsp.rust_analyzer.setup { + capabilities = capabilities, + settings = { ["rust-analyzer"] = { + cargo = { allFeatures = true }, + check = { command = "clippy" }, + } }, + } + lsp.hls.setup { + capabilities = capabilities, + settings = { haskell = { + formattingProvider = "fourmolu", + } }, + } + lsp.lua_ls.setup { + capabilities = capabilities, + settings = { Lua = { + diagnostics = { globals = { + "vim", + } }, + telemetry = { + enable = false, + }, + } } + } + lsp.templ.setup(mkCap()) + lsp.emmet_ls.setup(mkCap()) + lsp.ts_ls.setup(mkCap()) + lsp.dockerls.setup(mkCap()) + lsp.dockerls.setup(mkCap()) + lsp.docker_compose_language_service.setup(mkCap()) + lsp.terraformls.setup(mkCap()) + lsp.nixd.setup { + capabilities = capabilities, + settings = { nixd = { + formatting = { command = { "nixfmt" } }, + } }, + } + lsp.astro.setup(mkCap()) + lsp.elixirls.setup { capabilities = capabilities, cmd = { "elixir-ls" } } + lsp.csharp_ls.setup(mkCap()) + lsp.zls.setup(mkCap()) + lsp.denols.setup(mkCap()) +end + +-- Plugins +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({ + { "Failid to clone lazy.nvim:zn", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress the any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup({ + { "folke/lazy.nvim", tag = "stable" }, + { + "catppuccin/nvim", + config = function() + require "catppuccin".setup { + background = { + light = "latte", + dark = "mocha", + }, + } + vim.cmd.colorscheme("catppuccin") + end, + priority = 1000, + }, + { + "stevearc/oil.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = true, + lazy = false, + keys = { { "-", vim.cmd.Oil } }, + }, + { + "nvim-treesitter/nvim-treesitter", + config = function() + require("nvim-treesitter.configs").setup { + ensure_installed = { + "vimdoc", + "rust", "go", "c", "zig", + "lua", "python", "haskell", + "fish", "bash", + "typescript", "svelte", "javascript", "css", "astro", "tsx", "prisma", + "nix", + "markdown", "typst", + "terraform", "hcl", + "sql", + "templ", + "html", "php", + "elixir", "heex", + }, + indent = { enable = true }, + highlight = { enable = true }, + } + end, + }, + { + "nvim-telescope/telescope.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + keys = { + { "<leader>f", function() require "telescope.builtin".find_files() end }, + { "<leader>/", function() require "telescope.builtin".live_grep() end }, + { "<leader>l", function() require "telescope.builtin".resume() end }, + { "<leader><space>", function() require "telescope.builtin".buffers() end }, + }, + build = ":TSUpdate", + }, + { + "neovim/nvim-lspconfig", + dependencies = { "hrsh7th/cmp-nvim-lsp" }, + config = setup_lsp, + }, + { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "saadparwaiz1/cmp_luasnip", + "L3MON4D3/LuaSnip", + "hrsh7th/cmp-omni", + }, + config = function() + local cmp = require "cmp" + local luasnip = require "luasnip" + cmp.setup { + completion = { autocomplete = false }, + sources = cmp.config.sources { + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "omni" }, + }, + snippet = { + expand = function(args) luasnip.lsp_expand(args.body) end, + }, + mapping = { + ["<c-l>"] = cmp.mapping.confirm({ select = true }), + ["<c-e>"] = cmp.mapping.abort(), + ["<c-b>"] = cmp.mapping.scroll_docs(-4), + ["<c-f>"] = cmp.mapping.scroll_docs(4), + ["<c-n>"] = function(fallback) + if cmp.visible() then + cmp.select_next_item() + else + fallback() + end + end, + ["<c-p>"] = function(fallback) + if cmp.visible() then + cmp.select_prev_item() + else + fallback() + end + end, + }, + } + end, + -- NOTE: If this is lazy, the `mapping`s from above don't + -- work when completing for the first time + lazy = false, + keys = { + { mode = "i", "<c-l>", function() require "cmp".complete() end }, + { mode = { "i", "s" }, "<c-h>", function() require "luasnip".jump(-1) end }, + { mode = { "i", "s" }, "<c-e>", function() require "luasnip".jump(1) end }, + }, + }, + { "wsdjeg/vim-fetch" }, + { + "ggandor/leap.nvim", + keys = { + { "s", function() require "leap".leap {} end }, + { "S", function() require "leap".leap { backward = true } end }, + }, + }, + { "numToStr/Comment.nvim", config = true }, + { "willothy/flatten.nvim", config = true, lazy = false }, + { "folke/todo-comments.nvim", config = true }, + { + "akinsho/bufferline.nvim", + after = "cattppuccin", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + require("bufferline").setup { + options = { diagnostics = "nvim_lsp" }, + highlights = require("catppuccin.groups.integrations.bufferline").get(), + } + end, + lazy = false, + keys = { + { "<leader>a", function() require "bufferline".go_to(1) end }, + { "<leader>r", function() require "bufferline".go_to(2) end }, + { "<leader>s", function() require "bufferline".go_to(3) end }, + { "<leader>t", function() require "bufferline".go_to(4) end }, + }, + }, + { "kylechui/nvim-surround", event = "VeryLazy", config = true }, + { + "folke/snacks.nvim", + priority = 1000, + lazy = false, + opts = { + input = { enabled = true }, + bigfile = { enabled = true }, + notifier = { enabled = true }, + indent = { enabled = true }, + terminal = { + win = { + keys = { + gf = function() + local cfile = vim.fn.expand("<cfile>") + local line = vim.fn.getline(".") + local match = line:match(vim.pesc(cfile) .. "(:%d+:%d+)") + if match == nil then + match = line:match(vim.pesc(cfile) .. "(:%d+)") + end + if match == nil then + match = "" + end + local f = vim.fn.findfile(cfile, "**") + -- Go to previous window because `:e fname:lineno:colnu` works thanks to wsdjeg/vim-fetch but not when in the terminal window + vim.cmd.wincmd("p") + vim.schedule(function() + vim.cmd.e(f .. match) + end) + end, + }, + }, + }, + }, + keys = { + { "<leader>q", function() Snacks.bufdelete() end }, + { "<leader>g", function() Snacks.lazygit() end }, + { "<leader>b", function() + local t, created = Snacks.terminal.get() + if created then + vim.schedule(function() + local autocmds = vim.api.nvim_get_autocmds({ event = "BufEnter", buffer = t.buf }) + -- Snacks.notify(vim.pretty_print(autocmds)) + vim.api.nvim_del_autocmd( + autocmds[1].id + ) + end) + else + t:show() + t:focus() + vim.cmd.startinsert() + end + end }, + }, + }, +}) + +-- Other +vim.api.nvim_create_user_command("Djul", function(opts) + local buf = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(buf, opts.line1 - 1, opts.line2, false) + for i, line in ipairs(lines) do + line = string.gsub(line, "…", "...") + line = string.gsub(line, "“", '"') + line = string.gsub(line, "”", '"') + line = string.gsub(line, "‘", "'") + line = string.gsub(line, "’", "'") + lines[i] = line + end + vim.api.nvim_buf_set_lines(buf, opts.line1 - 1, opts.line2, false, lines) +end, { range = "%" }) + +local busctl_buffer = "" +vim.system({ "busctl", "--user", "monitor", "org.freedesktop.portal.Desktop", "--json=short" }, { + text = true, + stdout = function(err, data) + if err ~= nil then + Snacks.notify(err) + return + end + busctl_buffer = busctl_buffer .. data + while true do + local lf = busctl_buffer:find("\n") + if lf == nil then break end + local packet = vim.json.decode(busctl_buffer:sub(1, lf - 1)) + busctl_buffer = busctl_buffer:sub(lf + 1) + + if packet.interface ~= "org.freedesktop.portal.Settings" then goto continue end + if packet.path ~= "/org/freedesktop/portal/desktop" then goto continue end + if packet.member ~= "SettingChanged" then goto continue end + if packet.payload.type ~= "ssv" then goto continue end + + if packet.payload.data[1] ~= "org.freedesktop.appearance" then goto continue end + if packet.payload.data[2] ~= "color-scheme" then goto continue end + if packet.payload.data[3].type ~= "u" then goto continue end + local value = packet.payload.data[3].data + vim.schedule(function() set.background = value == 1 and "dark" or "light" end) + ::continue:: + end + end, + detach = true, +}) diff --git a/dot-config/nvim/lazy-lock.json b/dot-config/nvim/lazy-lock.json new file mode 100644 index 0000000..6dbe3ce --- /dev/null +++ b/dot-config/nvim/lazy-lock.json @@ -0,0 +1,23 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "LuaSnip": { "branch": "master", "commit": "fb525166ccc30296fb3457441eb979113de46b00" }, + "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "a8912b88ce488f411177fc8aed358b04dc246d7b" }, + "cmp-omni": { "branch": "main", "commit": "4ef610bbd85a5ee4e97e09450c0daecbdc60de86" }, + "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, + "flatten.nvim": { "branch": "main", "commit": "72527798e75b5e34757491947c2cb853ce21dc0e" }, + "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, + "leap.nvim": { "branch": "main", "commit": "10c14af4ddfb34dbd7721f0bfb2b4d91f0558907" }, + "nvim": { "branch": "main", "commit": "fa42eb5e26819ef58884257d5ae95dd0552b9a66" }, + "nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" }, + "nvim-lspconfig": { "branch": "master", "commit": "9276b82935bf6b951d08c864eb5ac3f85d6b743b" }, + "nvim-surround": { "branch": "main", "commit": "8dd9150ca7eae5683660ea20cec86edcd5ca4046" }, + "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, + "nvim-web-devicons": { "branch": "master", "commit": "1fb58cca9aebbc4fd32b086cb413548ce132c127" }, + "oil.nvim": { "branch": "master", "commit": "08c2bce8b00fd780fb7999dbffdf7cd174e896fb" }, + "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, + "snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" }, + "telescope.nvim": { "branch": "master", "commit": "b4da76be54691e854d3e0e02c36b0245f945c2c7" }, + "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, + "vim-fetch": { "branch": "master", "commit": "db3fd95eb0cf7e7e9effa1338b286db33e4a36c1" } +} diff --git a/dot-config/systemd/user/yubikey-agent.service.d/override.conf b/dot-config/systemd/user/yubikey-agent.service.d/override.conf new file mode 100644 index 0000000..a71cd7f --- /dev/null +++ b/dot-config/systemd/user/yubikey-agent.service.d/override.conf @@ -0,0 +1,3 @@ +[Service] +Environment=WAYLAND_DISPLAY=wayland-1 +Environment=DISPLAY=:0 diff --git a/dot-config/waybar/config.jsonc b/dot-config/waybar/config.jsonc new file mode 100644 index 0000000..143dc31 --- /dev/null +++ b/dot-config/waybar/config.jsonc @@ -0,0 +1,171 @@ +[{ + "output": ["eDP-1"], + // "layer": "top", // Waybar at top layer + "height": 32, + "position": "top", // Waybar position (top|bottom|left|right) + // "width": 1280, // Waybar width + "spacing": 4, // Gaps between modules (4px) + // Choose the order of the modules + "modules-left": [ + "network", + "bluetooth", + "mpris" + ], + "modules-center": [ + // "wlr/taskbar", + "clock" + ], + "modules-right": [ + "privacy", + + "idle_inhibitor", + + "temperature", + "load", + "memory", + + "wireplumber", + "backlight", + "battery", + + "group/power", + "tray" + ], + "wlr/taskbar": { + "tooltip-format": "{title} | {app_id}" + }, + "group/power": { + "orientation": "inherit", + "drawer": { + "children-class": "power-child", + "transition-left-to-right": false, + }, + "modules": [ + "custom/poweroff", + "custom/suspend", + "custom/reboot" + ] + }, + "custom/reboot": { + "format": "", + "on-click": "reboot", + "tooltip": false + }, + "custom/suspend": { + "format": "", + "on-click": "systemctl suspend", + "tooltip": false + }, + "custom/poweroff": { + "format": "", + "on-click": "shutdown now", + "tooltip": false + }, + "privacy": { + "icon-size": 17 + }, + "network": { + "format-wifi": " {essid} {ipaddr}/{cidr}", + "format-ethernet": " {ipaddr}/{cidr}", + "tooltip": false + }, + "bluetooth": { + "format-on": "", + "format-disabled": "", + "format-off": "", + "on-click": "blueman-manager" + }, + "mpris": { + "format": " {status_icon} {dynamic}", + "interval": 1, + "dynamic-len": 40, + "status-icons": { + "playing": "▶", + "paused": "⏸", + "stopped": "" + }, + "dynamic-order": ["title", "artist"], + "ignored-players": ["brave"] + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "" + }, + "tooltip": "Idle inhibitor" + }, + "sway/mode": { + "format": "{}" + }, + "sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" + }, + "tray": { + "icon-size": 14, + "spacing": 10 + }, + "load": { + "format": " {}" + }, + "cpu": { + "format": "{usage}% ", + "tooltip": false + }, + "memory": { + "format": " {}%" + }, + "temperature": { + // "thermal-zone": 2, + // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input", + "critical-threshold": 80, + // "format-critical": "{temperatureC}°C {icon}", + "format": "{temperatureC}°C {icon}", + "format-icons": ["", "", ""], + "tooltip": false + }, + "backlight": { + "on-scroll-up": "brightnessctl set +1", + "on-scroll-down": "brightnessctl set 1-", + "format": " {percent}%", + "tooltip": false + }, + "battery": { + "states": { + "warning": 30, + "critical": 15 + }, + "format": "{icon} {capacity}%", + "format-full": "{icon} {capacity}%", + "format-charging": " {capacity}%", + "format-plugged": " {capacity}%", + "format-icons": ["", "", "", "", ""] + }, + "wireplumber": { + "scroll-step": 1, // %, can be a float + "format": "{icon} {volume}%", + "format-bluetooth": "{icon} {volume}% ", + "format-bluetooth-muted": " {icon}", + "format-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle", + "tooltip": false + }, + "clock": { + "format": "{:%A %Y-%m-%d %H:%M:%S}", + "interval": 1, + "tooltip": false + } +}] diff --git a/dot-config/waybar/style.css b/dot-config/waybar/style.css new file mode 100644 index 0000000..438d30f --- /dev/null +++ b/dot-config/waybar/style.css @@ -0,0 +1,193 @@ +* { + font-size: 14px; + border-radius: 4px; +} + +window#waybar { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: FontAwesome, monospace; + background-color: transparent; + border-bottom: 0px; + color: #ebdbb2; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden { + opacity: 0.2; +} + +window#waybar.empty #window { + background-color: transparent; +} + +/* +window#waybar.empty { + background-color: transparent; +} +window#waybar.solo { + background-color: #FFFFFF; +} +*/ + +.modules-right { + margin: 10px 6px 0 0; +} +.modules-center { + margin: 10px 0 0 0; +} +.modules-left { + margin: 10px 0 0 6px; +} + +button { + /* Use box-shadow instead of border so the text isn't offset */ + /* box-shadow: inset 0 -3px transparent; */ + border: none; +} + +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +/* +button:hover { + background: inherit; + box-shadow: inset 0 -3px #ebdbb2; +} */ + +#workspaces { + background-color: #282828; +} + +#workspaces button { + padding: 0 5px; + background-color: transparent; + color: #ebdbb2; + border-radius: 0; +} + +#workspaces button:first-child { + border-radius: 5px 0 0 5px; +} + +#workspaces button:last-child { + border-radius: 0 5px 5px 0; +} + +#workspaces button:hover { + color: #d79921; +} + +#workspaces button.focused { + background-color: #665c54; + /* box-shadow: inset 0 -3px #ffffff; */ +} + +#workspaces button.urgent { + background-color: #b16286; +} + +#idle_inhibitor, +#cava, +#scratchpad, +#mode, +#window, +#clock, +#battery, +#backlight, +#wireplumber, +#tray, +#mpris, +#network, +#temperature, +#bluetooth, +#memory, +#custom-poweroff, +#custom-reboot, +#custom-suspend, +#load { + padding: 0 10px; + background-color: #282828; + color: #ebdbb2; +} + +#custom-reboot, +#custom-suspend { + margin-right: 3px; +} + +#privacy { + padding: 0 10px; + background-color: #bc4b3c; + color: #ebdbb2; +} + +#mode { + background-color: #689d6a; + color: #282828; + /* box-shadow: inset 0 -3px #ffffff; */ +} + +/* If workspaces is the leftmost module, omit left margin */ +.modules-left > widget:first-child > #workspaces { + margin-left: 0; +} + +/* If workspaces is the rightmost module, omit right margin */ +.modules-right > widget:last-child > #workspaces { + margin-right: 0; +} + +#cava { + padding: 0 5px; +} + +#battery.charging, #battery.plugged { + background-color: #98971a; + color: #282828; +} + +@keyframes blink { + to { + background-color: #282828; + color: #ebdbb2; + } +} + +/* Using steps() instead of linear as a timing function to limit cpu usage */ +#battery.critical:not(.charging) { + background-color: #cc241d; + color: #ebdbb2; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: steps(12); + animation-iteration-count: infinite; + animation-direction: alternate; +} + +label:focus { + background-color: #000000; +} + +#wireplumber.muted { + background-color: #458588; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; +} + +#mpris.playing { + background-color: #d79921; + color: #282828; +} + +#tray menu { + font-family: sans-serif; +} + +#scratchpad.empty { + background: transparent; +} diff --git a/dot-local-bin/brightness b/dot-local-bin/brightness new file mode 100755 index 0000000..ab365a9 --- /dev/null +++ b/dot-local-bin/brightness @@ -0,0 +1,7 @@ +#!/usr/bin/env fish + +brightnessctl set $argv[1] + +set curr (math -s0 -mround (brightnessctl get) / (brightnessctl max) "*" 100) + +notify-send -t 1000 -a 'brightness' -h int:value:$curr " $curr" diff --git a/dot-local-bin/dark-light-switch b/dot-local-bin/dark-light-switch new file mode 100755 index 0000000..488b71a --- /dev/null +++ b/dot-local-bin/dark-light-switch @@ -0,0 +1,7 @@ +#!/usr/bin/env fish + +if [ (gsettings get org.gnome.desktop.interface color-scheme) = "'prefer-dark'" ] + gsettings set org.gnome.desktop.interface color-scheme prefer-light +else + gsettings set org.gnome.desktop.interface color-scheme prefer-dark +end diff --git a/dot-local-bin/wp-vol b/dot-local-bin/wp-vol new file mode 100755 index 0000000..4ae235c --- /dev/null +++ b/dot-local-bin/wp-vol @@ -0,0 +1,8 @@ +#!/usr/bin/env fish + +wpctl set-volume @DEFAULT_AUDIO_SINK@ $argv[1] + +# Get the volume level and convert it to a percentage +set volume (math -s0 -mround (wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{print $2}') "*" 100) + +notify-send -t 1000 -a 'wp-vol' -h int:value:$volume " $volume" diff --git a/etc/ssh/ssh_config.d/my.conf b/etc/ssh/ssh_config.d/my.conf new file mode 100644 index 0000000..0ed5c8b --- /dev/null +++ b/etc/ssh/ssh_config.d/my.conf @@ -0,0 +1,4 @@ +Host * + UserKnownHostsFile ~/.local/share/ssh/known_hosts + ServerAliveInterval 60 + SetEnv TERM=xterm-256color @@ -0,0 +1,29 @@ +#!/usr/bin/env fish + +set homedirs dot-config dot-local-bin + +for dir in $homedirs + set -l target_base $HOME/(string replace '-' '/' (string replace -r '^dot-' '.' $dir)) + + for file in (find $dir -type f) + set -l src "$(pwd)/$file" + set -l dst (string replace -r "^$dir/" "$target_base/" $file) + if [ -L $dst -a "$(readlink $dst)" = $src ] + continue + end + mkdir -p "$(dirname $dst)" + ln -vs $src $dst + end +end + +for file in (find etc -type f) + set -l src "$(pwd)/$file" + set -l dst /$file + if [ -f $dst ] + if [ "$(sha1sum < $dst)" = "$(sha1sum < $src)" ] + continue + end + end + sudo -p "[sudo] password to copy $dst: " mkdir -p "$(dirname $dst)" + sudo cp -v $src $dst +end |