1 Commits

Author SHA1 Message Date
100b8e40f9 [nix-darwin] Bump flake.lock, add claude-code
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 11:57:09 -08:00
134 changed files with 2542 additions and 6209 deletions

View File

@@ -1,54 +0,0 @@
name: Deploy to GitHub Pages
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Emacs
uses: purcell/setup-emacs@master
with:
version: 29.1
- name: Setup Cask
uses: conao3/setup-cask@master
with:
version: snapshot
- name: Install dependencies
working-directory: gen-gh-pages
run: cask install
- name: Generate HTML
working-directory: gen-gh-pages
run: |
cask exec emacs --script generate-html.el
mv ../dotfiles/emacs.d/README.html ./index.html
- name: Deploy to GitHub Pages
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./gen-gh-pages
publish_branch: gh-pages
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
commit_message: 'Deploy to GitHub Pages: ${{ github.sha }}'
keep_files: false

1
.gitignore vendored
View File

@@ -25,4 +25,3 @@ gotools
/dotfiles/config/gtk-3.0/colors.css
/dotfiles/emacs.d/.cache/
/dotfiles/config/fontconfig/conf.d/10-hm-fonts.conf
/dotfiles/config/fontconfig/conf.d/52-hm-default-fonts.conf

View File

@@ -1,152 +0,0 @@
# Org-Agenda-API Consolidation Design
## Overview
Consolidate org-agenda-api container builds and fly.io deployment into the dotfiles repository. This eliminates the separate `colonelpanic-org-agenda-api` repo and provides:
- Container outputs available to NixOS machines directly
- Fly.io deployment from the same repo
- Fewer repos to maintain
- Cachix integration for faster builds
## Directory Structure
```
/home/imalison/dotfiles/
├── nixos/
│ ├── flake.nix # Main flake, adds container output
│ ├── org-agenda-api.nix # Existing tangling module (stays here)
│ └── ...
├── org-agenda-api/
│ ├── container.nix # Container build logic (mkContainer, etc.)
│ ├── configs/
│ │ ├── colonelpanic/
│ │ │ ├── custom-config.el
│ │ │ └── overrides.el (optional)
│ │ └── kat/
│ │ └── custom-config.el
│ ├── fly/
│ │ ├── fly.toml
│ │ ├── deploy.sh
│ │ └── config-{instance}.env
│ └── secrets/
│ ├── secrets.nix # agenix declarations
│ └── *.age # encrypted secrets
└── dotfiles/emacs.d/
└── org-config.org # Source of truth for org config
```
## Flake Integration
The main dotfiles flake at `/home/imalison/dotfiles/nixos/flake.nix` exposes container outputs:
```nix
outputs = inputs @ { self, nixpkgs, flake-utils, ... }:
{
nixosConfigurations = { ... }; # existing
} // flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
containerLib = import ../org-agenda-api/container.nix {
inherit pkgs system;
tangledConfig = (import ./org-agenda-api.nix {
inherit pkgs system;
inputs = inputs;
}).org-agenda-custom-config;
};
in {
packages = {
container-colonelpanic = containerLib.mkInstanceContainer "colonelpanic";
container-kat = containerLib.mkInstanceContainer "kat";
};
}
);
```
Build with: `nix build .#container-colonelpanic`
## Custom Elisp & Tangling
Single source of truth: `org-config.org` tangles to elisp files loaded by containers.
**What stays in custom-config.el (container-specific glue):**
- Path overrides (`/data/org` instead of `~/org`)
- Stubs for unavailable packages (`org-bullets-mode` no-op)
- Customize-to-setq format conversion
- Template conversion for org-agenda-api format
- Instance-specific settings
**Audit:** During implementation, verify no actual org logic is duplicated in custom-config.el.
## Cachix Integration
### Phase 1: Use upstream cache as substituter
Add to dotfiles flake's `nixConfig`:
```nix
nixConfig = {
extra-substituters = [
"https://org-agenda-api.cachix.org"
];
extra-trusted-public-keys = [
"org-agenda-api.cachix.org-1:PUBLIC_KEY_HERE"
];
};
```
Benefits:
- `container-base` (~500MB+ dependencies) fetched from cache
- Rebuilds only process the small custom config layer
### Phase 2 (future): Push custom builds
Set up GitHub Action or local push for colonelpanic-specific container builds.
## Fly.io Deployment
**What moves:**
- `fly.toml``dotfiles/org-agenda-api/fly/fly.toml`
- `deploy.sh``dotfiles/org-agenda-api/fly/deploy.sh`
- `configs/*/config.env``dotfiles/org-agenda-api/fly/config-{instance}.env`
- Agenix secrets → `dotfiles/org-agenda-api/secrets/`
**Deploy script changes:**
- Build path: `nix build "../nixos#container-${INSTANCE}"`
- Secrets path adjusts to new location
- Otherwise same logic
## Implementation Phases
### Phase 1: Pull latest & verify current state
- Pull latest changes in org-agenda-api and colonelpanic-org-agenda-api
- Build container, verify it works
- Fix any issues before restructuring
### Phase 2: Create dotfiles structure
- Create `/home/imalison/dotfiles/org-agenda-api/` directory
- Move container.nix logic (adapted from current colonelpanic-org-agenda-api flake)
- Move instance configs (colonelpanic/, kat/)
- Move fly.io deployment files
- Move agenix secrets
### Phase 3: Integrate with dotfiles flake
- Update `/home/imalison/dotfiles/nixos/flake.nix` to expose container outputs
- Add cachix substituter configuration
- Test build from dotfiles: `nix build .#container-colonelpanic`
### Phase 4: Verify deployment
- Test deploy.sh from new location
- Verify fly.io deployment works
- Run the container locally on a NixOS machine
### Phase 5: Audit & cleanup
- Review custom-config.el for any duplicated org logic
- Archive colonelpanic-org-agenda-api repo
- Update any references/documentation
## Repos Affected
- **dotfiles** - Receives container build + fly.io deployment
- **colonelpanic-org-agenda-api** - Becomes obsolete after migration
- **org-agenda-api** (upstream) - No changes, used as flake input

View File

@@ -1,21 +0,0 @@
# Agentic Session Preferences
## Tmux session titling
- If the TMUX environment variable is set, treat this chat as the controller for the current tmux session.
- Maintain a session/window/pane title that updates when the task focus changes substantially.
- Prefer automatic titling: infer a concise <task> from the current user request and context without asking.
- Title format: "<project> - <task>".
- <project> is the basename of the current project directory.
- Prefer git repo root basename if available; otherwise use basename of the current working directory.
- <task> is a short, user-friendly description of what we are doing.
- Ask for a short descriptive <task> only when the task is ambiguous or you are not confident in an inferred title.
- When the task changes substantially, update the <task> automatically if clear; otherwise ask for an updated <task>.
- When a title is provided or updated, immediately run this one-liner:
tmux rename-session '<project> - <task>' \; rename-window '<project> - <task>' \; select-pane -T '<project> - <task>'
- Assume you are inside tmux, so do not use -t unless the user asks to target a specific session.
- For Claude Code sessions, a UserPromptSubmit hook will also update titles automatically based on the latest prompt.
## Pane usage
- Do not create extra panes or windows unless the user asks.

View File

@@ -1,70 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ -z "${TMUX:-}" ]]; then
exit 0
fi
input=$(cat)
read -r cwd prompt <<'PY' < <(python3 - <<'PY'
import json, os, sys
try:
data = json.load(sys.stdin)
except Exception:
data = {}
cwd = data.get("cwd") or os.getcwd()
prompt = (data.get("prompt") or "").strip()
print(cwd)
print(prompt)
PY
)
if [[ -z "${cwd}" ]]; then
cwd="$PWD"
fi
project_root=$(git -C "$cwd" rev-parse --show-toplevel 2>/dev/null || true)
if [[ -n "$project_root" ]]; then
project=$(basename "$project_root")
else
project=$(basename "$cwd")
fi
prompt_first_line=$(printf '%s' "$prompt" | head -n 1 | tr '\n' ' ' | sed -e 's/[[:space:]]\+/ /g' -e 's/^ *//; s/ *$//')
lower=$(printf '%s' "$prompt_first_line" | tr '[:upper:]' '[:lower:]')
case "$lower" in
""|"ok"|"okay"|"thanks"|"thx"|"cool"|"yep"|"yes"|"no"|"sure"|"done"|"k")
exit 0
;;
esac
task="$prompt_first_line"
if [[ -z "$task" ]]; then
task="work"
fi
# Trim to a reasonable length for tmux status bars.
if [[ ${#task} -gt 60 ]]; then
task="${task:0:57}..."
fi
title="$project - $task"
state_dir="${HOME}/.agents/state"
state_file="$state_dir/tmux-title"
mkdir -p "$state_dir"
if [[ -f "$state_file" ]]; then
last_title=$(cat "$state_file" 2>/dev/null || true)
if [[ "$last_title" == "$title" ]]; then
exit 0
fi
fi
printf '%s' "$title" > "$state_file"
# Update session, window, and pane titles.
tmux rename-session "$title" \; rename-window "$title" \; select-pane -T "$title"

View File

@@ -1 +0,0 @@
../agents/AGENTS.md

View File

@@ -1,18 +0,0 @@
{
"enabledPlugins": {
"superpowers@superpowers-marketplace": true,
"agent-browser@agent-browser": true
},
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "~/.agents/hooks/tmux-title.sh"
}
]
}
]
}
}

View File

@@ -1,51 +0,0 @@
{
"permissions": {
"allow": [
"Bash(find:*)",
"Bash(cat:*)"
],
"deny": []
},
"mcp": {
"servers": {
"gitea-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITEA_ACCESS_TOKEN=ad1e513137d5a15b638f7b4b5f65e1bda1c70cd7",
"-e",
"GITEA_BASE_URL=https://dev.railbird.ai",
"docker.gitea.com/gitea-mcp-server"
],
"env": {
"GITEA_ACCESS_TOKEN": "ad1e513137d5a15b638f7b4b5f65e1bda1c70cd7",
"GITEA_BASE_URL": "https://dev.railbird.ai"
}
},
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--auto-connect"
]
},
"imap-email": {
"command": "npx",
"args": ["-y", "imap-email-mcp"],
"env": {
"IMAP_USER": "IvanMalison@gmail.com",
"IMAP_PASSWORD": "iiobqyuuczibsnmi",
"IMAP_HOST": "imap.gmail.com"
}
}
}
},
"enabledMcpjsonServers": [
"chrome-devtools",
"imap-email"
],
"enableAllProjectMcpServers": true
}

View File

@@ -1 +0,0 @@
../agents/AGENTS.md

View File

@@ -1,56 +0,0 @@
model = "gpt-5.2-codex"
model_reasoning_effort = "high"
personality = "pragmatic"
[projects."/home/imalison/Projects/nixpkgs"]
trust_level = "trusted"
[projects."/home/imalison/dotfiles"]
trust_level = "trusted"
[projects."/home/imalison/Projects/railbird"]
trust_level = "trusted"
[projects."/home/imalison/Projects/subtr-actor"]
trust_level = "trusted"
[projects."/home/imalison/Projects/google-messages-api"]
trust_level = "trusted"
[projects."/home/imalison"]
trust_level = "trusted"
[projects."/home/imalison/Projects/scrobble-scrubber"]
trust_level = "trusted"
[projects."/home/imalison/temp"]
trust_level = "trusted"
[projects."/home/imalison/Projects/org-agenda-api"]
trust_level = "untrusted"
[projects."/home/imalison/org"]
trust_level = "trusted"
[notice]
hide_gpt5_1_migration_prompt = true
"hide_gpt-5.1-codex-max_migration_prompt" = true
[notice.model_migrations]
"gpt-5.2" = "gpt-5.2-codex"
[mcp_servers.chrome-devtools]
command = "npx"
args = ["-y", "chrome-devtools-mcp@latest", "--auto-connect"]
[mcp_servers.observability]
command = "npx"
args = ["-y", "@google-cloud/observability-mcp"]
[mcp_servers.gmail]
command = "nix"
args = ["run", "/home/imalison/Projects/gmail-mcp#gmail-mcp-server"]
[features]
unified_exec = true
apps = true
steer = true

View File

@@ -2,7 +2,7 @@
import = ["~/.config/alacritty/themes/themes/dracula.toml"]
[font]
size = 12
size = 8
[scrolling]
history = 10000

View File

@@ -1,39 +0,0 @@
output DP-1
off
output HDMI-1
off
output DP-2
off
output HDMI-2
off
output DP-1-0
off
output DP-1-1
off
output DP-1-2
off
output DP-1-3
off
output DP-1-4
off
output DP-1-5
off
output DP-1-6
off
output eDP-1
crtc 0
mode 2560x1600
pos 0x0
primary
rate 240.00
x-prop-broadcast_rgb Automatic
x-prop-colorspace Default
x-prop-max_bpc 12
x-prop-non_desktop 0
x-prop-scaling_mode Full aspect
output HDMI-1-0
crtc 4
mode 3440x1440
pos 2560x0
rate 99.98
x-prop-non_desktop 0

View File

@@ -1,2 +0,0 @@
HDMI-1-0 00ffffffffffff0010ace3a1535a333016210103805123782a25a1b14d3db7250e505421080001010101010101010101010101010101e77c70a0d0a029503020350029623100001a000000ff00237442737a474441594542634e000000fd0018781e963c010a202020202020000000fc0044656c6c204157333432334457015f020337f148101f04130312013f230907018301000068030c002000383c006ad85dc401788000000278e305c000e2006ae60605018d4b004ed470a0d0a046503020350029623100001a9d6770a0d0a022503020350029623100001a565e00a0a0a029503020350029623100001a6fc200a0a0a055503020350029623100001a3c
eDP-1 00ffffffffffff0009e5580c0000000001210104b527187803bbc5ae503fb7250c515500000001010101010101010101010101010101c07200a0a040c8603020360084f21000001a000000fd0c30f0b1b176010a202020202020000000fe00424f452043510a202020202020000000fc004e4531383051444d2d4e4d310a029602030f00e3058080e606050195731000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa702079020021001d280f7409000a400680dd2a511824b249120e023554b060ec64662a1378220014ffed1185ff099f002f001f003f06c700020005002b000c27003cef00002700303b0000810015741a0000030b30f0006095107310f0000000008d00000000000000000000000000000000000000000000000000000000bc90

View File

@@ -1,39 +0,0 @@
output DP-1
off
output HDMI-1
off
output DP-2
off
output HDMI-2
off
output DP-1-0
off
output DP-1-1
off
output DP-1-2
off
output DP-1-3
off
output DP-1-4
off
output DP-1-5
off
output DP-1-6
off
output eDP-1
crtc 0
mode 2560x1600
pos 0x0
primary
rate 240.00
x-prop-broadcast_rgb Automatic
x-prop-colorspace Default
x-prop-max_bpc 12
x-prop-non_desktop 0
x-prop-scaling_mode Full aspect
output HDMI-1-0
crtc 4
mode 3440x1440
pos 2560x0
rate 99.98
x-prop-non_desktop 0

View File

@@ -1,2 +0,0 @@
HDMI-1-0 00ffffffffffff0010ace3a1535a333016210103805123782a25a1b14d3db7250e505421080001010101010101010101010101010101e77c70a0d0a029503020350029623100001a000000ff00237442737a474441594542634e000000fd0018781e963c010a202020202020000000fc0044656c6c204157333432334457015f020337f148101f04130312013f230907018301000068030c003000383c006ad85dc401788000000278e305c000e2006ae60605018d4b004ed470a0d0a046503020350029623100001a9d6770a0d0a022503020350029623100001a565e00a0a0a029503020350029623100001a6fc200a0a0a055503020350029623100001a2c
eDP-1 00ffffffffffff0009e5580c0000000001210104b527187803bbc5ae503fb7250c515500000001010101010101010101010101010101c07200a0a040c8603020360084f21000001a000000fd0c30f0b1b176010a202020202020000000fe00424f452043510a202020202020000000fc004e4531383051444d2d4e4d310a029602030f00e3058080e606050195731000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa702079020021001d280f7409000a400680dd2a511824b249120e023554b060ec64662a1378220014ffed1185ff099f002f001f003f06c700020005002b000c27003cef00002700303b0000810015741a0000030b30f0006095107310f0000000008d00000000000000000000000000000000000000000000000000000000bc90

View File

@@ -0,0 +1,27 @@
[rc]
use_copy=true
use_primary=true
synchronize=false
automatic_paste=false
show_indexes=true
save_uris=true
use_rmb_menu=false
save_history=true
history_limit=1000
history_timeout_seconds=30
history_timeout=false
items_menu=50
statics_show=true
statics_items=10
hyperlinks_only=false
confirm_clear=false
single_line=false
reverse_history=false
item_length=50
ellipsize=2
history_key=
actions_key=
menu_key=
search_key=
offline_key=
offline_mode=false

View File

@@ -1,36 +1,25 @@
# Hyprland Configuration
# XMonad-like dynamic tiling using hy3 plugin
# Based on XMonad configuration from xmonad.hs
# =============================================================================
# PLUGINS (Hyprland pinned to 0.53.0 to match hy3)
# =============================================================================
# Load the plugin before parsing keybinds/layouts that depend on it
plugin = /run/current-system/sw/lib/libhy3.so
plugin = /run/current-system/sw/lib/libhyprexpo.so
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,auto
# =============================================================================
# MONITORS
# =============================================================================
monitor=,preferred,auto,1
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# =============================================================================
# PROGRAMS
# =============================================================================
# Set programs that you use
$terminal = alacritty
$fileManager = dolphin
$menu = rofi -show drun -show-icons
$runMenu = rofi -show run
# =============================================================================
# ENVIRONMENT VARIABLES
# =============================================================================
# Environment variables
env = XCURSOR_SIZE,24
env = QT_QPA_PLATFORMTHEME,qt5ct
env = GDK_DPI_SCALE,1.25
env = QT_FONT_DPI,120
# =============================================================================
# INPUT CONFIGURATION
# =============================================================================
# Input configuration
input {
kb_layout = us
kb_variant =
@@ -44,252 +33,110 @@ input {
natural_scroll = no
}
sensitivity = 0
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
}
# Cursor warping behavior
cursor {
persistent_warps = true
}
# =============================================================================
# GENERAL SETTINGS
# =============================================================================
# General settings
general {
gaps_in = 5
gaps_out = 10
gaps_out = 20
border_size = 2
col.active_border = rgba(edb443ee) rgba(33ccffee) 45deg
col.inactive_border = rgba(595959aa)
# Use hy3 layout for XMonad-like dynamic tiling
layout = hy3
layout = master
allow_tearing = false
}
# =============================================================================
# DECORATION
# =============================================================================
# Decoration
decoration {
rounding = 5
rounding = 10
blur {
enabled = true
size = 3
passes = 1
}
# Fade inactive windows (like XMonad's fadeInactive)
active_opacity = 1.0
inactive_opacity = 0.9
}
# =============================================================================
# ANIMATIONS
# =============================================================================
# Animations
animations {
enabled = yes
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
bezier = linear, 0, 0, 1, 1
animation = windows, 1, 4, myBezier
animation = windowsOut, 1, 4, default, popin 80%
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation = borderangle, 1, 8, default
animation = fade, 1, 4, default
animation = workspaces, 1, 4, default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
# Layout configuration
dwindle {
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = yes # you probably want this
}
# =============================================================================
# MASTER LAYOUT CONFIGURATION
# =============================================================================
master {
new_status = slave
mfact = 0.5
mfact = 0.25
orientation = left
}
# Dwindle layout (alternative - binary tree like i3)
dwindle {
pseudotile = yes
preserve_split = yes
}
# =============================================================================
# WORKSPACE RULES (SMART GAPS)
# =============================================================================
# Replace no_gaps_when_only (removed in newer Hyprland)
# Remove gaps when there's only one visible tiled window (ignore special workspaces)
workspace = w[tv1]s[false], gapsout:0, gapsin:0
workspace = f[1]s[false], gapsout:0, gapsin:0
# Group/tabbed window configuration (built-in alternative to hy3 tabs)
group {
col.border_active = rgba(edb443ff)
col.border_inactive = rgba(091f2eff)
groupbar {
enabled = true
font_size = 12
height = 22
col.active = rgba(edb443ff)
col.inactive = rgba(091f2eff)
text_color = rgba(091f2eff)
}
}
# =============================================================================
# HY3/HYPREXPO PLUGIN CONFIG
# =============================================================================
plugin {
hy3 {
# Disable autotile to get XMonad-like manual control
autotile {
enable = false
}
# Tab configuration
tabs {
height = 22
padding = 6
render_text = true
text_font = "Sans"
text_height = 10
text_padding = 3
col.active = rgba(edb443ff)
col.inactive = rgba(091f2eff)
col.urgent = rgba(ff0000ff)
col.text.active = rgba(091f2eff)
col.text.inactive = rgba(ffffffff)
col.text.urgent = rgba(ffffffff)
}
}
hyprexpo {
# Always include workspace 1 in the overview grid
workspace_method = first 1
# Only show workspaces with windows
skip_empty = true
# 3 columns -> 3x3 grid when 9 workspaces are visible
columns = 3
}
}
# =============================================================================
# MISC
# =============================================================================
# Misc
misc {
force_default_wallpaper = 0
disable_hyprland_logo = true
}
# =============================================================================
# BINDS OPTIONS
# =============================================================================
binds {
# Keep workspace history so "previous" can toggle back reliably.
allow_workspace_cycles = true
workspace_back_and_forth = true
}
# Scratchpad-like windows
windowrule = float, title:^(htop)$
windowrule = size 80% 80%, title:^(htop)$
# =============================================================================
# WINDOW RULES
# =============================================================================
# Float dialogs
windowrulev2 = float, class:^()$,title:^()$
windowrulev2 = float, title:^(Picture-in-Picture)$
windowrulev2 = float, title:^(Open File)$
windowrulev2 = float, title:^(Save File)$
windowrulev2 = float, title:^(Confirm)$
# Chrome specific rules
windowrule = float, class:^(chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrule = float, class:^(chrome)$,title:^(Messages)$
windowrule = size 90% 90%, class:^(chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrule = size 90% 90%, class:^(chrome)$,title:^(Messages)$
# Scratchpad windows - float and size
windowrulev2 = workspace special:htop silent, class:^(htop-scratch)$
windowrulev2 = float, class:^(htop-scratch)$
windowrulev2 = size 90% 90%, class:^(htop-scratch)$
windowrulev2 = center, class:^(htop-scratch)$
# ===== KEY BINDINGS =====
# Based on XMonad configuration
windowrulev2 = workspace special:volume silent, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = float, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = size 90% 90%, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = center, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = workspace special:spotify silent, class:^(spotify)$
windowrulev2 = float, class:^(spotify)$
windowrulev2 = size 90% 90%, class:^(spotify)$
windowrulev2 = center, class:^(spotify)$
windowrulev2 = workspace special:element silent, class:^(Element)$
windowrulev2 = float, class:^(Element)$
windowrulev2 = size 90% 90%, class:^(Element)$
windowrulev2 = center, class:^(Element)$
windowrulev2 = workspace special:slack silent, class:^(Slack)$
windowrulev2 = float, class:^(Slack)$
windowrulev2 = size 90% 90%, class:^(Slack)$
windowrulev2 = center, class:^(Slack)$
windowrulev2 = workspace special:transmission silent, class:^(transmission-gtk)$
windowrulev2 = float, class:^(transmission-gtk)$
windowrulev2 = size 90% 90%, class:^(transmission-gtk)$
windowrulev2 = center, class:^(transmission-gtk)$
# Gmail and Messages (Chrome windows)
windowrulev2 = workspace special:gmail silent, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = float, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = center, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = workspace special:messages silent, class:^(google-chrome)$,title:^(Messages.*)$
windowrulev2 = float, class:^(google-chrome)$,title:^(Messages.*)$
windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(Messages.*)$
windowrulev2 = center, class:^(google-chrome)$,title:^(Messages.*)$
# =============================================================================
# KEY BINDINGS
# =============================================================================
# Modifier keys
# Main modifier key (Super/Windows key equivalent to mod4Mask)
$mainMod = SUPER
$modAlt = SUPER ALT
$hyper = SUPER CTRL ALT
# -----------------------------------------------------------------------------
# Program Launching
# -----------------------------------------------------------------------------
# Mod+Alt combination (equivalent to modalt in XMonad)
$modAlt = SUPER_ALT
# Hyper key (equivalent to mod3Mask in XMonad)
$hyper = ALT_R
# Program launching
bind = $mainMod, P, exec, $menu
bind = $mainMod SHIFT, P, exec, $runMenu
bind = $mainMod SHIFT, Return, exec, $terminal
# -----------------------------------------------------------------------------
# Overview (Hyprexpo)
# -----------------------------------------------------------------------------
bind = $mainMod, TAB, hyprexpo:expo, toggle
bind = $mainMod, Q, killactive,
bind = $mainMod SHIFT, C, killactive,
bind = $mainMod SHIFT, Q, exit,
# Emacs-everywhere (like XMonad's emacs-everywhere)
bind = $mainMod, E, exec, emacsclient --eval '(emacs-everywhere)'
bind = $mainMod, V, exec, wl-paste | xdotool type --file -
bind = $mainMod, E, exec, emacsclient -c
bind = $mainMod, V, exec, xclip -o | xdotool type --file -
# Chrome/Browser (raise or spawn like XMonad's bindBringAndRaise)
bind = $modAlt, C, exec, ~/.config/hypr/scripts/raise-or-run.sh google-chrome google-chrome-stable
# Chrome/Browser launching (equivalent to bindBringAndRaise)
bind = $modAlt, C, exec, google-chrome-stable
# -----------------------------------------------------------------------------
# SCRATCHPADS (Special Workspaces)
# -----------------------------------------------------------------------------
# Toggle scratchpads
bind = $modAlt, E, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh element '^Element$' - element-desktop
bind = $modAlt, G, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh gmail '^google-chrome$' '.*@gmail.com.*Gmail.*' google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox
bind = $modAlt, H, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh htop '^htop-scratch$' - alacritty --class htop-scratch --title htop -e htop
bind = $modAlt, M, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh messages '^google-chrome$' '^Messages.*' google-chrome-stable --new-window https://messages.google.com/web/conversations
bind = $modAlt, K, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh slack '^Slack$' - slack
bind = $modAlt, S, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh spotify '^spotify$' - spotify
bind = $modAlt, T, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh transmission '^transmission-gtk$' - transmission-gtk
bind = $modAlt, V, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh volume '^(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$' - pavucontrol
# Scratchpad equivalents (toggle special workspaces)
bind = $modAlt, E, togglespecialworkspace, element
bind = $modAlt, G, togglespecialworkspace, gmail
bind = $modAlt, H, togglespecialworkspace, htop
bind = $modAlt, M, togglespecialworkspace, messages
bind = $modAlt, K, togglespecialworkspace, slack
bind = $modAlt, S, togglespecialworkspace, spotify
bind = $modAlt, T, togglespecialworkspace, transmission
bind = $modAlt, V, togglespecialworkspace, volume
# Move windows to scratchpads
# Move windows to special workspaces
bind = $modAlt SHIFT, E, movetoworkspace, special:element
bind = $modAlt SHIFT, G, movetoworkspace, special:gmail
bind = $modAlt SHIFT, H, movetoworkspace, special:htop
@@ -299,113 +146,56 @@ bind = $modAlt SHIFT, S, movetoworkspace, special:spotify
bind = $modAlt SHIFT, T, movetoworkspace, special:transmission
bind = $modAlt SHIFT, V, movetoworkspace, special:volume
# Hidden workspace (like XMonad's NSP)
bind = $mainMod, X, movetoworkspace, special:NSP
bind = $mainMod SHIFT, X, togglespecialworkspace, NSP
# Directional navigation (WASD keys as in XMonad)
bind = $mainMod, W, movefocus, u
bind = $mainMod, S, movefocus, d
bind = $mainMod, A, movefocus, l
bind = $mainMod, D, movefocus, r
# -----------------------------------------------------------------------------
# DIRECTIONAL NAVIGATION (WASD - like XMonad Navigation2D)
# Using hy3 dispatchers for proper tree-based navigation
# -----------------------------------------------------------------------------
# Move windows directionally
bind = $mainMod SHIFT, W, movewindow, u
bind = $mainMod SHIFT, S, movewindow, d
bind = $mainMod SHIFT, A, movewindow, l
bind = $mainMod SHIFT, D, movewindow, r
# Focus movement (Mod + WASD) - hy3:movefocus navigates the tree
bind = $mainMod, W, hy3:movefocus, u
bind = $mainMod, S, hy3:movefocus, d
bind = $mainMod, A, hy3:movefocus, l
bind = $mainMod, D, hy3:movefocus, r
# Resize windows
bind = $mainMod CTRL, W, resizeactive, 0 -50
bind = $mainMod CTRL, S, resizeactive, 0 50
bind = $mainMod CTRL, A, resizeactive, -50 0
bind = $mainMod CTRL, D, resizeactive, 50 0
# Move windows (Mod + Shift + WASD) - hy3:movewindow with once=true for swapping
bind = $mainMod SHIFT, W, hy3:movewindow, u, once
bind = $mainMod SHIFT, S, hy3:movewindow, d, once
bind = $mainMod SHIFT, A, hy3:movewindow, l, once
bind = $mainMod SHIFT, D, hy3:movewindow, r, once
# Resize windows (Mod + Ctrl + WASD)
binde = $mainMod CTRL, W, resizeactive, 0 -50
binde = $mainMod CTRL, S, resizeactive, 0 50
binde = $mainMod CTRL, A, resizeactive, -50 0
binde = $mainMod CTRL, D, resizeactive, 50 0
# Screen/Monitor focus (Hyper + WASD)
bind = $hyper, W, focusmonitor, u
bind = $hyper, S, focusmonitor, d
bind = $hyper, A, focusmonitor, l
bind = $hyper, D, focusmonitor, r
# Move window to monitor and follow (Hyper + Shift + WASD)
bind = $hyper SHIFT, W, movewindow, mon:u
bind = $hyper SHIFT, S, movewindow, mon:d
bind = $hyper SHIFT, A, movewindow, mon:l
bind = $hyper SHIFT, D, movewindow, mon:r
# Shift to empty workspace on screen direction (Hyper + Ctrl + WASD)
# Like XMonad's shiftToEmptyOnScreen
bind = $hyper CTRL, W, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh u
bind = $hyper CTRL, S, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh d
bind = $hyper CTRL, A, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh l
bind = $hyper CTRL, D, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh r
# -----------------------------------------------------------------------------
# LAYOUT CONTROL (XMonad-like with hy3)
# -----------------------------------------------------------------------------
# Create groups with different orientations (like XMonad layouts)
# hy3:makegroup creates a split/tab group from focused window
bind = $mainMod, Space, hy3:changegroup, toggletab
bind = $mainMod SHIFT, Space, hy3:changegroup, opposite
# Create specific group types
bind = $mainMod, H, hy3:makegroup, h
bind = $mainMod SHIFT, V, hy3:makegroup, v
# Mod+Ctrl+Space mirrors Mod+Space (tabs instead of fullscreen)
bind = $mainMod CTRL, Space, hy3:changegroup, toggletab
# Change group type (cycle h -> v -> tab)
bind = $mainMod, slash, hy3:changegroup, h
bind = $mainMod SHIFT, slash, hy3:changegroup, v
# Tab navigation (like XMonad's focus next/prev in tabbed)
bind = $mainMod, bracketright, hy3:focustab, r, wrap
bind = $mainMod, bracketleft, hy3:focustab, l, wrap
# Move window within tab group (hy3 has no movetab dispatcher)
bind = $mainMod SHIFT, bracketright, hy3:movewindow, r, visible
bind = $mainMod SHIFT, bracketleft, hy3:movewindow, l, visible
# Expand focus to parent group (like XMonad's focus parent)
bind = $mainMod, grave, hy3:expand, expand
bind = $mainMod SHIFT, grave, hy3:expand, base
# Fullscreen (like XMonad's NBFULL toggle)
# Layout control
bind = $mainMod, Space, exec, hyprctl dispatch layoutmsg cyclenext
bind = $mainMod CTRL, Space, fullscreen, 0
bind = $mainMod, slash, exec, hyprctl dispatch layoutmsg orientationcycle left top
bind = $mainMod, F, fullscreen, 0
bind = $mainMod SHIFT, F, fullscreen, 1
# Toggle floating
bind = $mainMod, T, togglefloating,
bind = $mainMod SHIFT, Y, pseudo, # dwindle pseudotile
bind = $mainMod, J, togglesplit, # dwindle split direction
bind = $mainMod, comma, exec, hyprctl dispatch splitratio -0.05
bind = $mainMod, period, exec, hyprctl dispatch splitratio +0.05
bind = $mainMod, N, exec, hyprctl dispatch layoutmsg addmaster
bind = $mainMod SHIFT, N, exec, hyprctl dispatch layoutmsg removemaster
# Resize split ratio (hy3 uses resizeactive for splits)
binde = $mainMod, comma, resizeactive, -50 0
binde = $mainMod, period, resizeactive, 50 0
# Focus manipulation
bind = $mainMod, Tab, exec, hyprctl dispatch focuswindow "class:$(hyprctl activewindow -j | jq -r '.class')"
bind = $mainMod, M, exec, hyprctl dispatch focuswindow "class:master"
# Equalize window sizes on workspace (hy3)
bind = $mainMod SHIFT, equal, hy3:equalize, workspace
# Monitor/Screen control
bind = $mainMod, Z, focusmonitor, +1
bind = $mainMod SHIFT, Z, movewindow, mon:+1
# Kill group - removes the focused window from its group
bind = $mainMod, N, hy3:killactive
# Window management
bind = $mainMod, G, exec, hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class)"' | rofi -dmenu -i -p "Go to window" | head -1 | xargs -I {} hyprctl dispatch focuswindow "title:{}"
bind = $mainMod, B, exec, SELECTION=$(hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class) [\(.address)]"' | rofi -dmenu -i -p "Bring window"); if [ -n "$SELECTION" ]; then ADDRESS=$(echo "$SELECTION" | sed 's/.*\[\(.*\)\]/\1/'); hyprctl dispatch movetoworkspace "$(hyprctl activeworkspace -j | jq -r '.id')",address:"$ADDRESS"; fi
bind = $mainMod SHIFT, B, exec, hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class)"' | rofi -dmenu -i -p "Replace window" | head -1 | xargs -I {} hyprctl dispatch swapwindow "title:{}"
bind = $mainMod, M, exec, hyprctl dispatch togglespecialworkspace minimized
bind = $mainMod SHIFT, M, exec, hyprctl dispatch movetoworkspace special:minimized
bind = $mainMod SHIFT, H, exec, EMPTY_WS=$(hyprctl workspaces -j | jq -r 'map(select(.windows == 0)) | .[0].id // empty'); if [ -z "$EMPTY_WS" ]; then EMPTY_WS=$(hyprctl workspaces -j | jq -r 'max_by(.id).id + 1'); fi; hyprctl dispatch movetoworkspace $EMPTY_WS && hyprctl dispatch workspace $EMPTY_WS
bind = $mainMod, X, exec, hyprctl dispatch movetoworkspace special:NSP
# hy3:setswallow - set a window to swallow newly spawned windows
bind = $mainMod, M, hy3:setswallow, toggle
# Minimize to special workspace (like XMonad's minimizeWindow)
bind = $mainMod SHIFT, M, movetoworkspace, special:minimized
# Restore last minimized
bind = $modAlt, Return, togglespecialworkspace, minimized
# -----------------------------------------------------------------------------
# WORKSPACE CONTROL
# -----------------------------------------------------------------------------
# Switch workspaces (1-9, 0=10)
# Workspace switching
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
@@ -417,7 +207,7 @@ bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move window to workspace
# Move windows to workspaces
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
@@ -429,76 +219,27 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Move and follow to workspace (like XMonad's shiftThenView)
bind = $mainMod CTRL, 1, movetoworkspacesilent, 1
bind = $mainMod CTRL, 1, workspace, 1
bind = $mainMod CTRL, 2, movetoworkspacesilent, 2
bind = $mainMod CTRL, 2, workspace, 2
bind = $mainMod CTRL, 3, movetoworkspacesilent, 3
bind = $mainMod CTRL, 3, workspace, 3
bind = $mainMod CTRL, 4, movetoworkspacesilent, 4
bind = $mainMod CTRL, 4, workspace, 4
bind = $mainMod CTRL, 5, movetoworkspacesilent, 5
bind = $mainMod CTRL, 5, workspace, 5
bind = $mainMod CTRL, 6, movetoworkspacesilent, 6
bind = $mainMod CTRL, 6, workspace, 6
bind = $mainMod CTRL, 7, movetoworkspacesilent, 7
bind = $mainMod CTRL, 7, workspace, 7
bind = $mainMod CTRL, 8, movetoworkspacesilent, 8
bind = $mainMod CTRL, 8, workspace, 8
bind = $mainMod CTRL, 9, movetoworkspacesilent, 9
bind = $mainMod CTRL, 9, workspace, 9
bind = $mainMod CTRL, 0, movetoworkspacesilent, 10
bind = $mainMod CTRL, 0, workspace, 10
# Move and follow to workspace
bind = $mainMod CTRL, 1, movetoworkspace, 1
bind = $mainMod CTRL, 2, movetoworkspace, 2
bind = $mainMod CTRL, 3, movetoworkspace, 3
bind = $mainMod CTRL, 4, movetoworkspace, 4
bind = $mainMod CTRL, 5, movetoworkspace, 5
bind = $mainMod CTRL, 6, movetoworkspace, 6
bind = $mainMod CTRL, 7, movetoworkspace, 7
bind = $mainMod CTRL, 8, movetoworkspace, 8
bind = $mainMod CTRL, 9, movetoworkspace, 9
bind = $mainMod CTRL, 0, movetoworkspace, 10
# Workspace cycling (like XMonad's cycleWorkspaceOnCurrentScreen)
bind = $mainMod, backslash, exec, ~/.config/hypr/scripts/workspace-back.sh
# Swap current workspace with another (like XMonad's swapWithCurrent)
bind = $hyper, 5, exec, ~/.config/hypr/scripts/swap-workspaces.sh
# Go to next empty workspace (like XMonad's moveTo Next emptyWS)
bind = $hyper, E, workspace, empty
# Move to next screen (like XMonad's shiftToNextScreenX)
bind = $mainMod, Z, focusmonitor, +1
bind = $mainMod SHIFT, Z, movewindow, mon:+1
# Shift to empty workspace and view (like XMonad's shiftToEmptyAndView)
bind = $mainMod SHIFT, H, movetoworkspace, empty
# -----------------------------------------------------------------------------
# WINDOW MANAGEMENT
# -----------------------------------------------------------------------------
# Go to window (rofi window switcher)
bind = $mainMod, G, exec, rofi -show window -show-icons
# Bring window (move to current workspace)
bind = $mainMod, B, exec, ~/.config/hypr/scripts/bring-window.sh
# Replace window (swap focused with selected - like XMonad's myReplaceWindow)
bind = $mainMod SHIFT, B, exec, ~/.config/hypr/scripts/replace-window.sh
# Gather windows of same class (like XMonad's gatherThisClass)
bind = $hyper, G, exec, ~/.config/hypr/scripts/gather-class.sh
# Focus next window of different class (like XMonad's focusNextClass)
bind = $mainMod, apostrophe, exec, ~/.config/hypr/scripts/focus-next-class.sh
# -----------------------------------------------------------------------------
# MEDIA KEYS
# -----------------------------------------------------------------------------
# Volume control (matching XMonad: Mod+I=up, Mod+K=down, Mod+U=mute)
binde = , XF86AudioRaiseVolume, exec, set_volume --unmute --change-volume +5
binde = , XF86AudioLowerVolume, exec, set_volume --unmute --change-volume -5
# Media keys and volume control
bind = , XF86AudioRaiseVolume, exec, set_volume --unmute --change-volume +5
bind = , XF86AudioLowerVolume, exec, set_volume --unmute --change-volume -5
bind = , XF86AudioMute, exec, set_volume --toggle-mute
binde = $mainMod, I, exec, set_volume --unmute --change-volume +5
binde = $mainMod, K, exec, set_volume --unmute --change-volume -5
bind = $mainMod, I, exec, set_volume --unmute --change-volume +5
bind = $mainMod, K, exec, set_volume --unmute --change-volume -5
bind = $mainMod, U, exec, set_volume --toggle-mute
# Media player controls (matching XMonad: Mod+;=play, Mod+L=next, Mod+J=prev)
# Media player controls
bind = $mainMod, semicolon, exec, playerctl play-pause
bind = , XF86AudioPlay, exec, playerctl play-pause
bind = , XF86AudioPause, exec, playerctl play-pause
@@ -507,67 +248,47 @@ bind = , XF86AudioNext, exec, playerctl next
bind = $mainMod, J, exec, playerctl previous
bind = , XF86AudioPrev, exec, playerctl previous
# Mute current window (like XMonad's toggle_mute_current_window)
bind = $hyper SHIFT, Q, exec, toggle_mute_current_window.sh
bind = $hyper CTRL, Q, exec, toggle_mute_current_window.sh only
# Brightness control
binde = , XF86MonBrightnessUp, exec, brightness.sh up
binde = , XF86MonBrightnessDown, exec, brightness.sh down
bind = , XF86MonBrightnessUp, exec, brightness.sh 5
bind = , XF86MonBrightnessDown, exec, brightness.sh -5
# -----------------------------------------------------------------------------
# UTILITY BINDINGS
# -----------------------------------------------------------------------------
bind = $hyper, V, exec, cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy
bind = $hyper, P, exec, rofi-pass
bind = $hyper, H, exec, grim -g "$(slurp)" - | swappy -f -
# Utility bindings
bind = $hyper, V, exec, rofi_clipit.sh
bind = $hyper, Y, exec, rofi-pass
bind = $hyper, H, exec, rofi_shutter
bind = $hyper, C, exec, shell_command.sh
bind = $hyper, X, exec, rofi_command.sh
bind = $hyper SHIFT, L, exec, hyprlock
bind = $hyper SHIFT, L, exec, dm-tool lock
bind = $hyper, K, exec, rofi_kill_process.sh
bind = $hyper SHIFT, K, exec, rofi_kill_all.sh
bind = $hyper, R, exec, rofi-systemd
bind = $hyper, 9, exec, start_synergy.sh
bind = $hyper, slash, exec, toggle_taffybar
bind = $hyper, Space, exec, skippy-xd
bind = $hyper, I, exec, rofi_select_input.hs
bind = $hyper, O, exec, rofi_paswitch
# Reload config
bind = $mainMod, apostrophe, exec, load_default_map
bind = $modAlt, apostrophe, exec, load_xkb_map
bind = $mainMod, R, exec, hyprctl reload
# -----------------------------------------------------------------------------
# MOUSE BINDINGS
# -----------------------------------------------------------------------------
# Workspace cycling
bind = $mainMod, backslash, workspace, previous
bind = $mainMod, Tab, workspace, previous
# Mouse bindings
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
# Scroll through workspaces
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# =============================================================================
# AUTOSTART
# =============================================================================
# Start Hyprland session target for systemd user services (e.g., waybar)
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE
exec-once = systemctl --user start hyprland-session.target
exec-once = ~/.config/hypr/scripts/workspace-history.sh
# Scratchpad applications (spawn on demand via keybinds)
# exec-once = [workspace special:element silent] element-desktop
# exec-once = [workspace special:gmail silent] google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox
# exec-once = [workspace special:htop silent] alacritty --class htop-scratch --title htop -e htop
# exec-once = [workspace special:messages silent] google-chrome-stable --new-window https://messages.google.com/web/conversations
# exec-once = [workspace special:slack silent] slack
# exec-once = [workspace special:spotify silent] spotify
# exec-once = [workspace special:transmission silent] transmission-gtk
# exec-once = [workspace special:volume silent] pavucontrol
# Clipboard history daemon
exec-once = wl-paste --type text --watch cliphist store
exec-once = wl-paste --type image --watch cliphist store
# Night light (optional - comment out if not needed)
# exec-once = wlsunset -l 37.7 -L -122.4
# Special workspaces for "scratchpad" applications
exec-once = [workspace special:element silent] element-desktop
exec-once = [workspace special:gmail silent] google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox
exec-once = [workspace special:htop silent] alacritty --title htop -e htop
exec-once = [workspace special:messages silent] google-chrome-stable --new-window https://messages.google.com/web/conversations
exec-once = [workspace special:slack silent] slack
exec-once = [workspace special:spotify silent] spotify
exec-once = [workspace special:transmission silent] transmission-gtk
exec-once = [workspace special:volume silent] pavucontrol

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Bring window to current workspace (like XMonad's bringWindow)
# Uses rofi to select a window and moves it to the current workspace
set -euo pipefail
# Get current workspace
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
# Get all windows and format for rofi
WINDOWS=$(hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0 and .workspace.id != '"$CURRENT_WS"') | "\(.title) [\(.class)] - WS:\(.workspace.id) |\(.address)"')
if [ -z "$WINDOWS" ]; then
notify-send "Bring Window" "No windows on other workspaces"
exit 0
fi
# Show rofi menu
SELECTION=$(echo "$WINDOWS" | rofi -dmenu -i -p "Bring window" -format 's')
if [ -n "$SELECTION" ]; then
# Extract the window address (after the last |)
ADDRESS=$(echo "$SELECTION" | sed 's/.*|//')
# Move window to current workspace
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$ADDRESS"
# Focus the window
hyprctl dispatch focuswindow "address:$ADDRESS"
fi

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env bash
# Cycle between master and dwindle layouts
# Like XMonad's NextLayout
set -euo pipefail
CURRENT=$(hyprctl getoption general:layout -j | jq -r '.str')
if [ "$CURRENT" = "master" ]; then
hyprctl keyword general:layout dwindle
notify-send "Layout" "Switched to Dwindle (binary tree)"
else
hyprctl keyword general:layout master
notify-send "Layout" "Switched to Master (XMonad-like)"
fi

View File

@@ -1,48 +0,0 @@
#!/usr/bin/env bash
# Focus next window of a different class (like XMonad's focusNextClass)
set -euo pipefail
# Get focused window class
FOCUSED_CLASS=$(hyprctl activewindow -j | jq -r '.class')
FOCUSED_ADDR=$(hyprctl activewindow -j | jq -r '.address')
if [ "$FOCUSED_CLASS" = "null" ] || [ -z "$FOCUSED_CLASS" ]; then
# No focused window, just focus any window
hyprctl dispatch cyclenext
exit 0
fi
# Get all unique classes
ALL_CLASSES=$(hyprctl clients -j | jq -r '[.[] | select(.workspace.id >= 0) | .class] | unique | .[]')
# Get sorted list of classes
CLASSES_ARRAY=()
while IFS= read -r class; do
CLASSES_ARRAY+=("$class")
done <<< "$ALL_CLASSES"
# Find current class index and get next class
CURRENT_INDEX=-1
for i in "${!CLASSES_ARRAY[@]}"; do
if [ "${CLASSES_ARRAY[$i]}" = "$FOCUSED_CLASS" ]; then
CURRENT_INDEX=$i
break
fi
done
if [ $CURRENT_INDEX -eq -1 ] || [ ${#CLASSES_ARRAY[@]} -le 1 ]; then
# Only one class or class not found
exit 0
fi
# Get next class (wrapping around)
NEXT_INDEX=$(( (CURRENT_INDEX + 1) % ${#CLASSES_ARRAY[@]} ))
NEXT_CLASS="${CLASSES_ARRAY[$NEXT_INDEX]}"
# Find first window of next class
NEXT_WINDOW=$(hyprctl clients -j | jq -r ".[] | select(.class == \"$NEXT_CLASS\" and .workspace.id >= 0) | .address" | head -1)
if [ -n "$NEXT_WINDOW" ]; then
hyprctl dispatch focuswindow "address:$NEXT_WINDOW"
fi

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Gather all windows of the same class as focused window (like XMonad's gatherThisClass)
set -euo pipefail
# Get focused window class
FOCUSED_CLASS=$(hyprctl activewindow -j | jq -r '.class')
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
if [ "$FOCUSED_CLASS" = "null" ] || [ -z "$FOCUSED_CLASS" ]; then
notify-send "Gather Class" "No focused window"
exit 0
fi
# Find all windows with same class on other workspaces
WINDOWS=$(hyprctl clients -j | jq -r ".[] | select(.class == \"$FOCUSED_CLASS\" and .workspace.id != $CURRENT_WS and .workspace.id >= 0) | .address")
if [ -z "$WINDOWS" ]; then
notify-send "Gather Class" "No other windows of class '$FOCUSED_CLASS'"
exit 0
fi
# Move each window to current workspace
COUNT=0
for ADDR in $WINDOWS; do
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$ADDR"
((COUNT++))
done
notify-send "Gather Class" "Gathered $COUNT windows of class '$FOCUSED_CLASS'"

View File

@@ -1,19 +0,0 @@
#!/usr/bin/env bash
# Raise existing window or run command (like XMonad's raiseNextMaybe)
# Usage: raise-or-run.sh <class-pattern> <command>
set -euo pipefail
CLASS_PATTERN="$1"
COMMAND="$2"
# Find windows matching the class pattern
MATCHING=$(hyprctl clients -j | jq -r ".[] | select(.class | test(\"$CLASS_PATTERN\"; \"i\")) | .address" | head -1)
if [ -n "$MATCHING" ]; then
# Window exists, focus it
hyprctl dispatch focuswindow "address:$MATCHING"
else
# No matching window, run the command
exec $COMMAND
fi

View File

@@ -1,33 +0,0 @@
#!/usr/bin/env bash
# Replace focused window with selected window (like XMonad's myReplaceWindow)
# Swaps the positions of focused window and selected window
set -euo pipefail
# Get current workspace and focused window
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
FOCUSED=$(hyprctl activewindow -j | jq -r '.address')
if [ "$FOCUSED" = "null" ] || [ -z "$FOCUSED" ]; then
notify-send "Replace Window" "No focused window"
exit 0
fi
# Get all windows except focused
WINDOWS=$(hyprctl clients -j | jq -r ".[] | select(.workspace.id >= 0 and .address != \"$FOCUSED\") | \"\(.title) [\(.class)] - WS:\(.workspace.id) |\(.address)\"")
if [ -z "$WINDOWS" ]; then
notify-send "Replace Window" "No other windows available"
exit 0
fi
# Show rofi menu
SELECTION=$(echo "$WINDOWS" | rofi -dmenu -i -p "Replace with" -format 's')
if [ -n "$SELECTION" ]; then
# Extract the window address
ADDRESS=$(echo "$SELECTION" | sed 's/.*|//')
# Swap windows using hy3
hyprctl dispatch hy3:movewindow "address:$ADDRESS"
fi

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env bash
# Shift window to empty workspace on screen in given direction
# Like XMonad's shiftToEmptyOnScreen
# Usage: shift-to-empty-on-screen.sh <direction: u|d|l|r>
set -euo pipefail
DIRECTION="$1"
# Track the current monitor so we can return
ORIG_MONITOR=$(hyprctl activeworkspace -j | jq -r '.monitor')
# Move focus to the screen in that direction
hyprctl dispatch focusmonitor "$DIRECTION"
# Get the monitor we're now on (target monitor)
MONITOR=$(hyprctl activeworkspace -j | jq -r '.monitor')
# If there is no monitor in that direction, bail
if [ "$MONITOR" = "$ORIG_MONITOR" ]; then
exit 0
fi
# Find an empty workspace or create one
# First check if there's an empty workspace on this monitor
EMPTY_WS=$(hyprctl workspaces -j | jq -r ".[] | select(.windows == 0 and .monitor == \"$MONITOR\") | .id" | head -1)
if [ -z "$EMPTY_WS" ]; then
# No empty workspace, find next available workspace number
MAX_WS=$(hyprctl workspaces -j | jq -r 'map(.id) | max')
EMPTY_WS=$((MAX_WS + 1))
fi
# Ensure the workspace exists on the target monitor
hyprctl dispatch workspace "$EMPTY_WS"
# Go back to original monitor and move the window (without following)
hyprctl dispatch focusmonitor "$ORIG_MONITOR"
hyprctl dispatch movetoworkspacesilent "$EMPTY_WS"

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env bash
# Swap the contents of the current workspace with another workspace.
# Intended to mirror XMonad's swapWithCurrent behavior.
set -euo pipefail
CURRENT_WS="$(hyprctl activeworkspace -j | jq -r '.id')"
if [[ -z "${CURRENT_WS}" || "${CURRENT_WS}" == "null" ]]; then
exit 0
fi
TARGET_WS="${1:-}"
if [[ -z "${TARGET_WS}" ]]; then
WS_LIST="$({
seq 1 10
hyprctl workspaces -j | jq -r '.[].id' 2>/dev/null || true
} | awk 'NF {print $1}' | awk '!seen[$0]++' | sort -n)"
TARGET_WS="$(printf "%s\n" "${WS_LIST}" | rofi -dmenu -p "Swap with workspace")"
fi
if [[ -z "${TARGET_WS}" || "${TARGET_WS}" == "null" ]]; then
exit 0
fi
if [[ "${TARGET_WS}" == "${CURRENT_WS}" ]]; then
exit 0
fi
if ! [[ "${TARGET_WS}" =~ ^-?[0-9]+$ ]]; then
notify-send "Swap Workspace" "Invalid workspace: ${TARGET_WS}"
exit 1
fi
WINDOWS_CURRENT="$(hyprctl clients -j | jq -r --arg ws "${CURRENT_WS}" '.[] | select((.workspace.id|tostring) == $ws) | .address')"
WINDOWS_TARGET="$(hyprctl clients -j | jq -r --arg ws "${TARGET_WS}" '.[] | select((.workspace.id|tostring) == $ws) | .address')"
for ADDR in ${WINDOWS_CURRENT}; do
hyprctl dispatch movetoworkspace "${TARGET_WS},address:${ADDR}"
done
for ADDR in ${WINDOWS_TARGET}; do
hyprctl dispatch movetoworkspace "${CURRENT_WS},address:${ADDR}"
done

View File

@@ -1,51 +0,0 @@
#!/usr/bin/env bash
# Toggle a named Hyprland scratchpad, spawning it if needed.
# Usage: toggle-scratchpad.sh <name> <class_regex|-> <title_regex|-> <command...>
set -euo pipefail
if [ "$#" -lt 4 ]; then
echo "usage: $0 <name> <class_regex|-> <title_regex|-> <command...>" >&2
exit 1
fi
NAME="$1"
shift
CLASS_REGEX="$1"
shift
TITLE_REGEX="$1"
shift
COMMAND=("$@")
if [ "$CLASS_REGEX" = "-" ]; then
CLASS_REGEX=""
fi
if [ "$TITLE_REGEX" = "-" ]; then
TITLE_REGEX=""
fi
if [ -z "$CLASS_REGEX" ] && [ -z "$TITLE_REGEX" ]; then
echo "toggle-scratchpad: provide a class or title regex" >&2
exit 1
fi
MATCHING=$(hyprctl clients -j | jq -r --arg cre "$CLASS_REGEX" --arg tre "$TITLE_REGEX" '
.[]
| select(
(($cre == "") or (.class | test($cre; "i")))
and
(($tre == "") or (.title | test($tre; "i")))
)
| .address
')
if [ -z "$MATCHING" ]; then
"${COMMAND[@]}" &
else
while IFS= read -r ADDR; do
[ -n "$ADDR" ] || continue
hyprctl dispatch movetoworkspacesilent "special:$NAME,address:$ADDR"
done <<< "$MATCHING"
fi
hyprctl dispatch togglespecialworkspace "$NAME"

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
state_dir="${runtime_dir}/hypr"
prev_file="${state_dir}/prev-workspace"
prev="$(cat "${prev_file}" 2>/dev/null || true)"
if [[ -z "${prev}" ]]; then
exit 0
fi
hyprctl dispatch workspace "${prev}" >/dev/null 2>&1 || true

View File

@@ -1,60 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
sig="${HYPRLAND_INSTANCE_SIGNATURE:-}"
if [[ -z "$sig" ]]; then
exit 0
fi
sock="${runtime_dir}/hypr/${sig}/.socket2.sock"
state_dir="${runtime_dir}/hypr"
last_file="${state_dir}/last-workspace"
prev_file="${state_dir}/prev-workspace"
mkdir -p "${state_dir}"
# Initialize current workspace to avoid empty state.
if command -v hyprctl >/dev/null 2>&1; then
cur_id="$(hyprctl activeworkspace -j | jq -r '.id' 2>/dev/null || true)"
if [[ -n "${cur_id}" && "${cur_id}" != "null" ]]; then
echo "${cur_id}" > "${last_file}"
fi
fi
# Wait for the event socket to be ready.
while [[ ! -S "${sock}" ]]; do
sleep 0.2
done
nc -U "${sock}" | while read -r line; do
case "${line}" in
workspace*">>"*)
payload="${line#*>>}"
# Handle workspacev2 payloads: id,name
if [[ "${payload}" == *","* ]]; then
ws_id="${payload%%,*}"
ws_name="${payload#*,}"
else
ws_id="${payload}"
ws_name="${payload}"
fi
# Ignore special/negative workspaces.
if [[ "${ws_id}" =~ ^- ]] || [[ "${ws_name}" == special:* ]]; then
continue
fi
ws_ident="${ws_name}"
if [[ -z "${ws_ident}" ]]; then
ws_ident="${ws_id}"
fi
prev="$(cat "${last_file}" 2>/dev/null || true)"
if [[ -n "${prev}" && "${ws_ident}" != "${prev}" ]]; then
echo "${prev}" > "${prev_file}"
fi
echo "${ws_ident}" > "${last_file}"
;;
esac
done

View File

@@ -8,7 +8,7 @@
*/
configuration {
font: "Fira Code 10";
font: "Noto Sans 10";
show-icons: true;
display-drun: "";
drun-display-format: "{name}";
@@ -25,7 +25,7 @@ window {
border: 0px;
border-color: @ac;
border-radius: 12px;
width: 40%;
width: 30%;
location: center;
x-offset: 0;
y-offset: 0;
@@ -36,6 +36,7 @@ prompt {
padding: 0.30% 1% 0% -0.5%;
background-color: @al;
text-color: @fg;
font: "Fira Code 12";
}
entry {

View File

@@ -5,8 +5,7 @@ configuration {
terminal: "alacritty";
sidebar-mode: false;
fullscreen: true;
/* Let rofi auto-detect DPI under Wayland/Xwayland to avoid blurry scaling. */
dpi: 0;
dpi: 100;
}
@theme "colorful/style_7.rasi"

View File

@@ -3,11 +3,11 @@
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
@@ -21,11 +21,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
@@ -39,11 +39,11 @@
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
@@ -57,11 +57,11 @@
"systems": "systems_3"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
@@ -70,16 +70,80 @@
"type": "github"
}
},
"git-ignore-nix": {
"flake-utils_4": {
"inputs": {
"nixpkgs": "nixpkgs_3"
"systems": "systems_4"
},
"locked": {
"lastModified": 1762808025,
"narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"fourmolu-011": {
"flake": false,
"locked": {
"narHash": "sha256-g/yDZXeLCHq/iXoZTaTYSb8l9CMny3AKsRQgWElagZI=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/fourmolu-0.11.0.0/fourmolu-0.11.0.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/fourmolu-0.11.0.0/fourmolu-0.11.0.0.tar.gz"
}
},
"fourmolu-012": {
"flake": false,
"locked": {
"narHash": "sha256-yru8ls67DMM6WSeVU6xDmmwa48I8S9CUv9NBaxSQ29M=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/fourmolu-0.12.0.0/fourmolu-0.12.0.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/fourmolu-0.12.0.0/fourmolu-0.12.0.0.tar.gz"
}
},
"git-ignore-nix": {
"inputs": {
"nixpkgs": [
"taffybar",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"ref": "master",
"repo": "gitignore.nix",
"type": "github"
}
},
"git-ignore-nix_2": {
"inputs": {
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1703887061,
"narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5",
"type": "github"
},
"original": {
@@ -90,20 +154,13 @@
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"taffybar",
"weeder-nix",
"pre-commit-hooks",
"nixpkgs"
]
},
"flake": false,
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
@@ -113,13 +170,30 @@
}
},
"gtk-sni-tray": {
"flake": false,
"inputs": {
"flake-utils": [
"taffybar",
"flake-utils"
],
"git-ignore-nix": [
"taffybar",
"git-ignore-nix"
],
"nixpkgs": [
"taffybar",
"nixpkgs"
],
"status-notifier-item": [
"taffybar",
"status-notifier-item"
]
},
"locked": {
"lastModified": 1760550917,
"narHash": "sha256-oELopLiVb7D1fzYHAiw/cbfNPHLQcOJ3Rz/I1gbk8IY=",
"lastModified": 1663379298,
"narHash": "sha256-m18+G7V1N+g/pPeKJG9hkblGA5c8QTnUYnsU5t14sOw=",
"owner": "taffybar",
"repo": "gtk-sni-tray",
"rev": "f6d1bf5dd64ac0f532b03ae01f5e1cc051116f09",
"rev": "1927d86308d34b5d21a709cf8ff5332ec5d37de4",
"type": "github"
},
"original": {
@@ -130,13 +204,26 @@
}
},
"gtk-strut": {
"flake": false,
"inputs": {
"flake-utils": [
"taffybar",
"flake-utils"
],
"git-ignore-nix": [
"taffybar",
"git-ignore-nix"
],
"nixpkgs": [
"taffybar",
"nixpkgs"
]
},
"locked": {
"lastModified": 1760550944,
"narHash": "sha256-S0saDsCA3aosU23jO5+jSXkbyrv7/C48o8GjsZrqF0I=",
"lastModified": 1663377859,
"narHash": "sha256-UrBd+R3NaJIDC2lt5gMafS3KBeLs83emm2YorX2cFCo=",
"owner": "taffybar",
"repo": "gtk-strut",
"rev": "5e0bf7f4b93b931a9c4b4a48b5d39de3ca8f02ae",
"rev": "d946eb230cdccf5afc063642b3215723e555990b",
"type": "github"
},
"original": {
@@ -146,39 +233,197 @@
"type": "github"
}
},
"nixpkgs": {
"haskell-hie-bios": {
"flake": false,
"locked": {
"lastModified": 1764252443,
"narHash": "sha256-U4G4dUSYWZYKtrF7/ozebD1B96at08SIhY4R9OaK1nw=",
"lastModified": 1686930638,
"narHash": "sha256-gfcxxHtZ2jUsiKNn/O4jEkfWF/2H04aTnaIvPDbtNlQ=",
"owner": "haskell",
"repo": "hie-bios",
"rev": "3d4fadfb0dc44cb287db9897ecfb503899d33513",
"type": "github"
},
"original": {
"owner": "haskell",
"repo": "hie-bios",
"type": "github"
}
},
"haskell-implicit-hie-cradle": {
"flake": false,
"locked": {
"lastModified": 1686495518,
"narHash": "sha256-OAe+zOkMZuoTfVEMnxnCT1cmPgRF/riAR8nVdomnwxo=",
"owner": "smunix",
"repo": "implicit-hie-cradle",
"rev": "d6aa00355898469af56cfd5e62f7fc8bd9959ded",
"type": "github"
},
"original": {
"owner": "smunix",
"ref": "smunix-patch-hls-0.5-1",
"repo": "implicit-hie-cradle",
"type": "github"
}
},
"haskell-language-server": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_3",
"fourmolu-011": "fourmolu-011",
"fourmolu-012": "fourmolu-012",
"gitignore": "gitignore",
"haskell-hie-bios": "haskell-hie-bios",
"haskell-implicit-hie-cradle": "haskell-implicit-hie-cradle",
"hiedb": "hiedb",
"hlint-35": "hlint-35",
"hlint-36": "hlint-36",
"lsp": "lsp",
"lsp-test": "lsp-test",
"lsp-types": "lsp-types",
"nixpkgs": "nixpkgs_2",
"ormolu-052": "ormolu-052",
"ormolu-07": "ormolu-07",
"stylish-haskell-0145": "stylish-haskell-0145"
},
"locked": {
"lastModified": 1693851896,
"narHash": "sha256-799JUHpBd2iMRCrTYDme5RsROKnIwSKBe2xYxgVN7QI=",
"owner": "colonelpanic8",
"repo": "nixpkgs",
"rev": "e1fc6c25b91d3d49dd02a156237721f12dbd86b2",
"repo": "haskell-language-server",
"rev": "ea368cef0673059fff95e953ef983109b5979dbc",
"type": "github"
},
"original": {
"owner": "colonelpanic8",
"ref": "remove-gi-gtk-hs-patch",
"repo": "nixpkgs",
"ref": "goto-dependency-definition-2",
"repo": "haskell-language-server",
"type": "github"
}
},
"hiedb": {
"flake": false,
"locked": {
"lastModified": 1691542357,
"narHash": "sha256-90ftphhoIo0CklJrjfCGQrZIUKZfdMJ2Og6tep9dmJ8=",
"owner": "nlander",
"repo": "HieDb",
"rev": "4eebfcf8fab54f24808e6301227d77ae64d2509c",
"type": "github"
},
"original": {
"owner": "nlander",
"ref": "all-new-functions",
"repo": "HieDb",
"type": "github"
}
},
"hlint-35": {
"flake": false,
"locked": {
"narHash": "sha256-qQNUlQQnahUGEO92Lm0RwjTGBGr2Yaw0KRuFRMoc5No=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/hlint-3.5/hlint-3.5.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/hlint-3.5/hlint-3.5.tar.gz"
}
},
"hlint-36": {
"flake": false,
"locked": {
"narHash": "sha256-fH4RYnWeuBqJI5d3Ba+Xs0BxYr0IYFH1OWO3k2iHGlU=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/hlint-3.6.1/hlint-3.6.1.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/hlint-3.6.1/hlint-3.6.1.tar.gz"
}
},
"lsp": {
"flake": false,
"locked": {
"narHash": "sha256-HcEfdYUrCHufEa+10M2wESjnK41xM/msd+t6r6JwQO0=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/lsp-2.2.0.0/lsp-2.2.0.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/lsp-2.2.0.0/lsp-2.2.0.0.tar.gz"
}
},
"lsp-test": {
"flake": false,
"locked": {
"narHash": "sha256-E1D3X2+I9ZTZLpHDEDTXexQFYpyG5byOFRIvRTeBsn8=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/lsp-test-0.16.0.0/lsp-test-0.16.0.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/lsp-test-0.16.0.0/lsp-test-0.16.0.0.tar.gz"
}
},
"lsp-types": {
"flake": false,
"locked": {
"narHash": "sha256-Oa5HuKdsdTSQUKtuSt06zVAq19Qxq5IJZObrnPwlB6s=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/lsp-types-2.0.2.0/lsp-types-2.0.2.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/lsp-types-2.0.2.0/lsp-types-2.0.2.0.tar.gz"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1702312524,
"narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=",
"path": "/nix/store/4fgs7yzsy2dqnjw8j42qlp9i1vgarzy0-source",
"rev": "a9bf124c46ef298113270b1f84a164865987a91c",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1730768919,
"narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=",
"lastModified": 1686874404,
"narHash": "sha256-u2Ss8z+sGaVlKtq7sCovQ8WvXY+OoXJmY1zmyxITiaY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a04d33c0c3f1a59a2c1cb0c6e34cd24500e5a1dc",
"rev": "efc10371d5c5b8d2d58bab6c1100753efacfe550",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"ref": "haskell-updates",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1689098530,
"narHash": "sha256-fxc/9f20wRyo/5ydkmZkX/Sh/ULa7RcT8h+cUv8p/44=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f2406198ea0e4e37d4380d0e20336c575b8f8ef9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1666603677,
"narHash": "sha256-apAEIj+z1iwMaMJ4tB21r/VTetfGDLDzuhXRHJknIAU=",
@@ -192,38 +437,41 @@
"type": "indirect"
}
},
"nixpkgs_4": {
"nixpkgs_5": {
"locked": {
"lastModified": 1764230294,
"narHash": "sha256-Z63xl5Scj3Y/zRBPAWq1eT68n2wBWGCIEF4waZ0bQBE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0d59e0290eefe0f12512043842d7096c4070f30e",
"type": "github"
"lastModified": 1702312524,
"narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=",
"path": "/nix/store/4fgs7yzsy2dqnjw8j42qlp9i1vgarzy0-source",
"rev": "a9bf124c46ef298113270b1f84a164865987a91c",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs_2"
},
"ormolu-052": {
"flake": false,
"locked": {
"lastModified": 1747372754,
"narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
"type": "github"
"narHash": "sha256-H7eqId488RBRxcf7flgJefAZmRgFJASJva+Oy7GG4q4=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/ormolu-0.5.2.0/ormolu-0.5.2.0.tar.gz"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
"type": "tarball",
"url": "https://hackage.haskell.org/package/ormolu-0.5.2.0/ormolu-0.5.2.0.tar.gz"
}
},
"ormolu-07": {
"flake": false,
"locked": {
"narHash": "sha256-5M5gNzSvsiQH1+0oexRByzf5EIET+0BFwR4fLIr2P7g=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/ormolu-0.7.1.0/ormolu-0.7.1.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/ormolu-0.7.1.0/ormolu-0.7.1.0.tar.gz"
}
},
"root": {
@@ -231,11 +479,24 @@
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"taffybar": "taffybar",
"xmonad": "xmonad"
"xmonad": "xmonad_2"
}
},
"status-notifier-item": {
"flake": false,
"inputs": {
"flake-utils": [
"taffybar",
"flake-utils"
],
"git-ignore-nix": [
"taffybar",
"git-ignore-nix"
],
"nixpkgs": [
"taffybar",
"nixpkgs"
]
},
"locked": {
"lastModified": 1641783528,
"narHash": "sha256-wJymJfYPFj4/r1e4kT/wt9FEsyCXo5JkkcOoozpuhag=",
@@ -250,6 +511,18 @@
"type": "github"
}
},
"stylish-haskell-0145": {
"flake": false,
"locked": {
"narHash": "sha256-EE7RFQ6q4Ek8daRgOpNMGepYLa9o8cM4OLjTNUSHQf0=",
"type": "tarball",
"url": "https://hackage.haskell.org/package/stylish-haskell-0.14.5.0/stylish-haskell-0.14.5.0.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://hackage.haskell.org/package/stylish-haskell-0.14.5.0/stylish-haskell-0.14.5.0.tar.gz"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
@@ -295,42 +568,53 @@
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"taffybar": {
"inputs": {
"flake-utils": "flake-utils_2",
"git-ignore-nix": "git-ignore-nix",
"gtk-sni-tray": "gtk-sni-tray",
"gtk-strut": "gtk-strut",
"nixpkgs": [
"nixpkgs"
],
"haskell-language-server": "haskell-language-server",
"nixpkgs": "nixpkgs_3",
"status-notifier-item": "status-notifier-item",
"weeder-nix": "weeder-nix",
"xmonad": [
"xmonad"
]
"xmonad": "xmonad"
},
"locked": {
"lastModified": 1760591109,
"narHash": "sha256-O21ayp5v2eccXdcwNjTK5ZB99ruK0Zt9CUaw5Rye42g=",
"lastModified": 1696612500,
"narHash": "sha256-Q19F91yVQviqxgY+FkvEwtX2vcw414eVtK8erim0NrU=",
"owner": "taffybar",
"repo": "taffybar",
"rev": "b256a711416036ca124fc9b3f89e7c957535e465",
"rev": "46eba89c2a4d4ffefe42c3ee4506d1b74c8e61fd",
"type": "github"
},
"original": {
"owner": "taffybar",
"ref": "master",
"repo": "taffybar",
"type": "github"
}
},
"unstable": {
"locked": {
"lastModified": 1764242076,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
"lastModified": 1689098530,
"narHash": "sha256-fxc/9f20wRyo/5ydkmZkX/Sh/ULa7RcT8h+cUv8p/44=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4",
"rev": "f2406198ea0e4e37d4380d0e20336c575b8f8ef9",
"type": "github"
},
"original": {
@@ -340,41 +624,66 @@
"type": "github"
}
},
"weeder-nix": {
"inputs": {
"nixpkgs": [
"taffybar",
"nixpkgs"
],
"pre-commit-hooks": "pre-commit-hooks"
},
"unstable_2": {
"locked": {
"lastModified": 1748252779,
"narHash": "sha256-kSyD/VDUX2m9c2vcuLBT2wnpYiVSHHlP9vuDTtsAtD8=",
"owner": "NorfairKing",
"repo": "weeder-nix",
"rev": "388df7a6f00220d1960118e1ad37cd86150d2c5a",
"lastModified": 1704538339,
"narHash": "sha256-1734d3mQuux9ySvwf6axRWZRBhtcZA9Q8eftD6EZg6U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "46ae0210ce163b3cba6c7da08840c1d63de9c701",
"type": "github"
},
"original": {
"owner": "NorfairKing",
"repo": "weeder-nix",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"xmonad": {
"inputs": {
"flake-utils": "flake-utils_3",
"git-ignore-nix": "git-ignore-nix",
"nixpkgs": "nixpkgs_4",
"flake-utils": [
"taffybar",
"flake-utils"
],
"git-ignore-nix": [
"taffybar",
"git-ignore-nix"
],
"nixpkgs": [
"taffybar",
"nixpkgs"
],
"unstable": "unstable"
},
"locked": {
"lastModified": 1763949843,
"narHash": "sha256-aJXmGPWKjXs7cagVzUE3fd2Fpc+sXnknM446AxHgvH0=",
"lastModified": 1687976934,
"narHash": "sha256-hUZmKy3jJ1+5rTGeQzfNR+LxgzmLaaeRVnbsJMEVw0Q=",
"owner": "xmonad",
"repo": "xmonad",
"rev": "97edef37a3ae10012272d692b5e1bc9b7013fc14",
"rev": "1aac6611d82065c9198e5584176058a9483fcbb0",
"type": "github"
},
"original": {
"owner": "xmonad",
"ref": "master",
"repo": "xmonad",
"type": "github"
}
},
"xmonad_2": {
"inputs": {
"flake-utils": "flake-utils_4",
"git-ignore-nix": "git-ignore-nix_2",
"nixpkgs": "nixpkgs_5",
"unstable": "unstable_2"
},
"locked": {
"lastModified": 1702895348,
"narHash": "sha256-ADRTw4DTfDCmsSFFWZKmvdmIjnEVY7pjjUxYytKXy1E=",
"owner": "xmonad",
"repo": "xmonad",
"rev": "c4cf4715f736fed77fb2af622c0760259ac2cf43",
"type": "github"
},
"original": {

View File

@@ -1,30 +1,15 @@
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:colonelpanic8/nixpkgs/remove-gi-gtk-hs-patch";
xmonad.url = "github:xmonad/xmonad/master";
taffybar = {
url = "github:taffybar/taffybar/master";
inputs.nixpkgs.follows = "nixpkgs";
inputs.xmonad.follows = "xmonad";
};
taffybar.url = "github:taffybar/taffybar";
};
outputs = { self, flake-utils, taffybar, nixpkgs, xmonad }:
let
hoverlay = final: prev: hself: hsuper:
{
taffybar = prev.haskell.lib.overrideCabal hsuper.taffybar (oa: {
hoverlay = final: prev: hself: hsuper: {
taffybar = hsuper.taffybar.overrideAttrs (old: {
doHaddock = false;
doCheck = false;
# Fix for GHC 9.4 where liftA2 is not in Prelude
postPatch = (oa.postPatch or "") + ''
substituteInPlace src/System/Taffybar/DBus/Client/Util.hs \
--replace-fail "import Control.Monad (forM)" \
"import Control.Monad (forM)
import Control.Applicative (liftA2)"
'';
});
# gi-gtk-hs patching is now handled by taffybar's fixVersionNamePackages overlay
imalison-taffybar = prev.haskell.lib.addPkgconfigDepends (
hself.callCabal2nix "imalison-taffybar"
(
@@ -49,9 +34,9 @@ import Control.Applicative (liftA2)"
};
defComp = { compiler = "ghc94"; };
overlay = xmonad.lib.fromHOL hoverlay defComp;
overlayList = [ taffybar.overlays.default overlay ];
overlays = [ taffybar.overlay overlay ];
in flake-utils.lib.eachDefaultSystem (system:
let pkgs = import nixpkgs { inherit system; overlays = overlayList; config.allowBroken = true; };
let pkgs = import nixpkgs { inherit system overlays; config.allowBroken = true; };
hpkgs = pkgs.lib.attrsets.getAttrFromPath (xmonad.lib.hpath defComp) pkgs;
in
{
@@ -63,11 +48,5 @@ import Control.Applicative (liftA2)"
];
};
defaultPackage = hpkgs.imalison-taffybar;
}) // {
inherit overlay;
overlays = {
default = overlay;
taffybar = taffybar.overlays.default;
};
} ;
}) // { inherit overlay overlays; } ;
}

View File

@@ -21,7 +21,7 @@ executable taffybar
, containers
, directory
, filepath
, gi-gtk3
, gi-gtk
, gtk-sni-tray
, gtk-strut
, haskell-gi-base

View File

@@ -28,6 +28,7 @@ import System.Log.Handler.Simple
import System.Log.Logger
import System.Process
import System.Taffybar
import System.Taffybar.Auth
import System.Taffybar.Context (appendHook)
import System.Taffybar.DBus
import System.Taffybar.DBus.Toggle
@@ -39,6 +40,7 @@ import System.Taffybar.Information.X11DesktopInfo
import System.Taffybar.SimpleConfig
import System.Taffybar.Util
import System.Taffybar.Widget
import System.Taffybar.Widget.Crypto
import System.Taffybar.Widget.Generic.Icon
import System.Taffybar.Widget.Generic.PollingGraph
import System.Taffybar.Widget.Generic.PollingLabel
@@ -172,6 +174,9 @@ main = do
{ clockUpdateStrategy = RoundedTargetInterval 60 0.0
, clockFormatString = "%a %b %_d, 🕑%I:%M %p"
}
myICP = deocrateWithSetClassAndBoxes "icp" $ cryptoPriceLabelWithIcon @"ICP-USD"
myBTC = deocrateWithSetClassAndBoxes "btc" $ cryptoPriceLabelWithIcon @"BTC-USD"
myETH = deocrateWithSetClassAndBoxes "eth" $ cryptoPriceLabelWithIcon @"ETH-USD"
myTray = deocrateWithSetClassAndBoxes "tray" $
sniTrayNewFromParams defaultTrayParams { trayLeftClickAction = PopupMenu
, trayRightClickAction = Activate
@@ -189,6 +194,9 @@ main = do
batteryWidgets = [myBatteryIcon, myBatteryText]
baseEndWidgets =
[ myTray
, myICP
, myBTC
, myETH
, myMpris
]
fullEndWidgets = baseEndWidgets ++ [ myCPU, myMem, myNet, myMpris ]
@@ -202,6 +210,7 @@ main = do
, barPadding = 0
, barHeight = ScreenRatio $ 1/27
, cssPaths = cssFiles
, startupHook = void $ setCMCAPIKey "f9e66366-9d42-4c6e-8d40-4194a0aaa329"
, centerWidgets = [ myClock ]
}
selectedConfig =

View File

@@ -1,103 +0,0 @@
// -*- mode: jsonc -*-
{
"height": 42,
"spacing": 4,
"modules-left": [
"hyprland/workspaces",
"hyprland/submap"
],
"modules-center": [
"hyprland/window"
],
"modules-right": [
"idle_inhibitor",
"pulseaudio",
"network",
"power-profiles-daemon",
"cpu",
"memory",
"custom/diskfree",
"temperature",
"backlight",
"battery",
"clock",
"tray"
],
"idle_inhibitor": {
"format": "INHIB {icon}",
"format-icons": {
"activated": "ON",
"deactivated": "OFF"
}
},
"tray": {
"spacing": 10
},
"clock": {
"format": "{:%H:%M}",
"tooltip-format": "{:%Y %B}\n{calendar}",
"format-alt": "{:%Y-%m-%d}"
},
"cpu": {
"format": "CPU {usage}%",
"tooltip": false
},
"memory": {
"format": "MEM {}%"
},
"custom/diskfree": {
"exec": "~/.config/waybar/scripts/diskfree",
"interval": 30,
"format": "DISK {text}",
"tooltip": false
},
"temperature": {
"critical-threshold": 80,
"format": "TEMP {temperatureC}C"
},
"backlight": {
"format": "BL {percent}%"
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "BAT {capacity}%",
"format-full": "BAT {capacity}%",
"format-charging": "BAT {capacity}% charging",
"format-plugged": "BAT {capacity}% plugged",
"format-alt": "BAT {time}"
},
"power-profiles-daemon": {
"format": "PWR {profile}",
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
"tooltip": true
},
"network": {
"format-wifi": "WIFI {essid} {signalStrength}%",
"format-ethernet": "ETH {ipaddr}/{cidr}",
"tooltip-format": "{ifname} via {gwaddr}",
"format-linked": "{ifname} (No IP)",
"format-disconnected": "NET disconnected",
"format-alt": "{ifname}: {ipaddr}/{cidr}"
},
"pulseaudio": {
"format": "VOL {volume}%",
"format-muted": "VOL muted",
"format-source": "MIC {volume}%",
"format-source-muted": "MIC muted",
"on-click": "pavucontrol"
},
"hyprland/workspaces": {
"format": "{id} {windows}",
"on-click": "activate",
"workspace-taskbar": {
"enable": true,
"update-active-window": true,
"format": "{icon}",
"icon-size": 24,
"on-click-window": "hyprctl dispatch focuswindow address:{address}"
}
}
}

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/waybar"
list_file="${config_dir}/disks"
mounts=()
if [[ -n "${WAYBAR_DISKS:-}" ]]; then
# Accept comma or space separated values.
IFS=', ' read -r -a mounts <<< "${WAYBAR_DISKS//:/,}"
elif [[ -f "$list_file" ]]; then
while IFS= read -r line; do
line="${line%%#*}"
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
[[ -z "$line" ]] && continue
mounts+=("$line")
done < "$list_file"
fi
if [[ ${#mounts[@]} -eq 0 ]]; then
mounts=("/")
fi
items=()
for mount in "${mounts[@]}"; do
if df_out=$(df -h --output=avail,target "$mount" 2>/dev/null | awk 'NR==2 {print $2, $1}'); then
items+=("$df_out")
fi
done
if [[ ${#items[@]} -eq 0 ]]; then
exit 0
fi
output=""
for item in "${items[@]}"; do
if [[ -n "$output" ]]; then
output+=" | "
fi
output+="$item"
done
printf '%s\n' "$output"

View File

@@ -1,361 +0,0 @@
* {
/* `otf-font-awesome` is required to be installed for icons */
font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif;
font-size: 14px;
}
window#waybar {
background-color: rgba(43, 48, 59, 0.5);
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff;
transition-property: background-color;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
/*
window#waybar.empty {
background-color: transparent;
}
window#waybar.solo {
background-color: #FFFFFF;
}
*/
window#waybar.termite {
background-color: #3F3F3F;
}
window#waybar.chromium {
background-color: #000000;
border: none;
}
button {
/* Use box-shadow instead of border so the text isn't offset */
box-shadow: inset 0 -3px transparent;
/* Avoid rounded borders under each button name */
border: none;
border-radius: 0;
}
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
button:hover {
background: inherit;
box-shadow: inset 0 -3px #ffffff;
}
/* you can set a style on hover for any module like this */
#pulseaudio:hover {
background-color: #a37800;
}
#workspaces button,
#taskbar button {
padding: 0 3px;
background-color: transparent;
color: #ffffff;
}
#workspaces button:hover,
#taskbar button:hover {
background: rgba(0, 0, 0, 0.2);
}
#workspaces button.focused,
#taskbar button.active,
#taskbar button.focused {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button.urgent,
#taskbar button.urgent {
background-color: #eb4d4b;
}
#workspaces .workspace-label {
padding: 0 2px;
}
#workspaces .taskbar-window {
padding: 0 2px;
}
#workspaces .taskbar-window.active {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces .taskbar-window label {
color: #ffffff;
}
#workspaces .taskbar-window image {
margin: 0 1px;
}
#mode {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#clock,
#battery,
#cpu,
#memory,
#disk,
#custom-diskfree,
#temperature,
#backlight,
#network,
#pulseaudio,
#wireplumber,
#custom-media,
#tray,
#mode,
#idle_inhibitor,
#scratchpad,
#power-profiles-daemon,
#mpd {
padding: 0 8px;
color: #ffffff;
}
#window,
#workspaces,
#taskbar {
margin: 0 4px;
}
/* If workspaces is the leftmost module, omit left margin */
.modules-left > widget:first-child > #workspaces,
.modules-left > widget:first-child > #taskbar {
margin-left: 0;
}
/* If workspaces is the rightmost module, omit right margin */
.modules-right > widget:last-child > #workspaces,
.modules-right > widget:last-child > #taskbar {
margin-right: 0;
}
#clock {
background-color: #64727D;
}
#battery {
background-color: #ffffff;
color: #000000;
}
#battery.charging, #battery.plugged {
color: #ffffff;
background-color: #26A65B;
}
@keyframes blink {
to {
background-color: #ffffff;
color: #000000;
}
}
/* Using steps() instead of linear as a timing function to limit cpu usage */
#battery.critical:not(.charging) {
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: steps(12);
animation-iteration-count: infinite;
animation-direction: alternate;
}
#power-profiles-daemon {
padding-right: 15px;
}
#power-profiles-daemon.performance {
background-color: #f53c3c;
color: #ffffff;
}
#power-profiles-daemon.balanced {
background-color: #2980b9;
color: #ffffff;
}
#power-profiles-daemon.power-saver {
background-color: #2ecc71;
color: #000000;
}
label:focus {
background-color: #000000;
}
#cpu {
background-color: #2ecc71;
color: #000000;
}
#memory {
background-color: #9b59b6;
}
#disk {
background-color: #964B00;
}
#custom-diskfree {
background-color: #964B00;
}
#backlight {
background-color: #90b1b1;
}
#network {
background-color: #2980b9;
}
#network.disconnected {
background-color: #f53c3c;
}
#pulseaudio {
background-color: #f1c40f;
color: #000000;
}
#pulseaudio.muted {
background-color: #90b1b1;
color: #2a5c45;
}
#wireplumber {
background-color: #fff0f5;
color: #000000;
}
#wireplumber.muted {
background-color: #f53c3c;
}
#custom-media {
background-color: #66cc99;
color: #2a5c45;
min-width: 100px;
}
#custom-media.custom-spotify {
background-color: #66cc99;
}
#custom-media.custom-vlc {
background-color: #ffa000;
}
#temperature {
background-color: #f0932b;
}
#temperature.critical {
background-color: #eb4d4b;
}
#tray {
background-color: #2980b9;
}
#tray > .passive {
-gtk-icon-effect: dim;
}
#tray > .needs-attention {
-gtk-icon-effect: highlight;
background-color: #eb4d4b;
}
#idle_inhibitor {
background-color: #2d3436;
}
#idle_inhibitor.activated {
background-color: #ecf0f1;
color: #2d3436;
}
#mpd {
background-color: #66cc99;
color: #2a5c45;
}
#mpd.disconnected {
background-color: #f53c3c;
}
#mpd.stopped {
background-color: #90b1b1;
}
#mpd.paused {
background-color: #51a37a;
}
#language {
background: #00b093;
color: #740864;
padding: 0 5px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state {
background: #97e1ad;
color: #000000;
padding: 0 0px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state > label {
padding: 0 5px;
}
#keyboard-state > label.locked {
background: rgba(0, 0, 0, 0.2);
}
#scratchpad {
background: rgba(0, 0, 0, 0.2);
}
#scratchpad.empty {
background-color: transparent;
}
#privacy {
padding: 0;
}
#privacy-item {
padding: 0 5px;
color: white;
}
#privacy-item.screenshare {
background-color: #cf5700;
}
#privacy-item.audio-in {
background-color: #1ca000;
}
#privacy-item.audio-out {
background-color: #0069d4;
}

View File

@@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
@@ -23,11 +23,11 @@
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
@@ -41,11 +41,29 @@
"systems": "systems_3"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
@@ -56,18 +74,19 @@
},
"git-ignore-nix": {
"inputs": {
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1762808025,
"narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"lastModified": 1694102001,
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"ref": "master",
"repo": "gitignore.nix",
"type": "github"
}
@@ -77,11 +96,11 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1762808025,
"narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"lastModified": 1694102001,
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6",
"type": "github"
},
"original": {
@@ -96,11 +115,11 @@
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1762808025,
"narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"lastModified": 1694102001,
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6",
"type": "github"
},
"original": {
@@ -112,12 +131,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1666603677,
"narHash": "sha256-apAEIj+z1iwMaMJ4tB21r/VTetfGDLDzuhXRHJknIAU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "074da18a72269cc5a6cf444dce42daea5649b2fe",
"type": "github"
"lastModified": 1693099187,
"narHash": "sha256-FXCc6OIghv9k4xYOhSMZI6bj7o56S8BJKzKtTKzdUVQ=",
"path": "/nix/store/wr9zk0l6xw1bi0zjrrsj998b5wgykyz5-source",
"rev": "cf2004afe4d4b95a295c63c911e949e40915eedb",
"type": "path"
},
"original": {
"id": "nixpkgs",
@@ -126,11 +144,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1769740369,
"narHash": "sha256-xKPyJoMoXfXpDM5DFDZDsi9PHArf2k5BJjvReYXoFpM=",
"lastModified": 1666603677,
"narHash": "sha256-apAEIj+z1iwMaMJ4tB21r/VTetfGDLDzuhXRHJknIAU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6308c3b21396534d8aaeac46179c14c439a89b8a",
"rev": "074da18a72269cc5a6cf444dce42daea5649b2fe",
"type": "github"
},
"original": {
@@ -166,11 +184,23 @@
"type": "indirect"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1693099187,
"narHash": "sha256-FXCc6OIghv9k4xYOhSMZI6bj7o56S8BJKzKtTKzdUVQ=",
"path": "/nix/store/wr9zk0l6xw1bi0zjrrsj998b5wgykyz5-source",
"rev": "cf2004afe4d4b95a295c63c911e949e40915eedb",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"git-ignore-nix": "git-ignore-nix",
"nixpkgs": "nixpkgs_2",
"nixpkgs": "nixpkgs",
"xmonad": "xmonad",
"xmonad-contrib": "xmonad-contrib"
}
@@ -220,13 +250,44 @@
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"unstable": {
"locked": {
"lastModified": 1769461804,
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"lastModified": 1696019113,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"unstable_2": {
"locked": {
"lastModified": 1696019113,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
"type": "github"
},
"original": {
@@ -239,49 +300,61 @@
"xmonad": {
"inputs": {
"flake-utils": "flake-utils_2",
"git-ignore-nix": "git-ignore-nix_2",
"git-ignore-nix": "git-ignore-nix",
"nixpkgs": [
"nixpkgs"
],
"unstable": "unstable"
},
"locked": {
"lastModified": 1767819257,
"narHash": "sha256-U7MIHr0B10wDSNgUvq4QTK22HZ4pl2oIYkdOKEMnxC4=",
"owner": "xmonad",
"repo": "xmonad",
"rev": "bb33042d408c15d8727011b1ed4aa22b2716d73d",
"type": "github"
"lastModified": 1,
"narHash": "sha256-dOrvPpypuNn/fAWY2XjMacpsAXEiMZ4Dll3Ot81iQL4=",
"path": "./xmonad",
"type": "path"
},
"original": {
"owner": "xmonad",
"repo": "xmonad",
"type": "github"
"path": "./xmonad",
"type": "path"
}
},
"xmonad-contrib": {
"inputs": {
"flake-utils": "flake-utils_3",
"git-ignore-nix": "git-ignore-nix_3",
"git-ignore-nix": "git-ignore-nix_2",
"nixpkgs": [
"nixpkgs"
],
"xmonad": [
"xmonad"
]
"xmonad": "xmonad_2"
},
"locked": {
"lastModified": 1755152326,
"narHash": "sha256-47gGXt1TxzfQx/6X895t/T8Ozj+7fmQdU1i4cwyxcSg=",
"owner": "IvanMalison",
"repo": "xmonad-contrib",
"rev": "1a8da46855ca83e11cfb31cbbaed980ed7a8dfcc",
"lastModified": 1,
"narHash": "sha256-MwbeBTfcf6vE7bQvha4ueg5zLZxBiU3678ESYrXD4lw=",
"path": "./xmonad-contrib",
"type": "path"
},
"original": {
"path": "./xmonad-contrib",
"type": "path"
}
},
"xmonad_2": {
"inputs": {
"flake-utils": "flake-utils_4",
"git-ignore-nix": "git-ignore-nix_3",
"nixpkgs": "nixpkgs_5",
"unstable": "unstable_2"
},
"locked": {
"lastModified": 1695471545,
"narHash": "sha256-3EK3rWNuPsc4FwkY7S1sPVI4hr9O7/AXI5AqdO0gJ/A=",
"owner": "xmonad",
"repo": "xmonad",
"rev": "327c2cf0c14f8eec234ec74d1a657d3e2fd5df11",
"type": "github"
},
"original": {
"owner": "IvanMalison",
"ref": "withMyChanges",
"repo": "xmonad-contrib",
"owner": "xmonad",
"repo": "xmonad",
"type": "github"
}
}

View File

@@ -1,18 +1,16 @@
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
git-ignore-nix.url = "github:hercules-ci/gitignore.nix";
xmonad = {
url = "github:xmonad/xmonad";
flake-utils.url = github:numtide/flake-utils;
xmonad-contrib = {
url = path:./xmonad-contrib;
inputs.nixpkgs.follows = "nixpkgs";
};
xmonad-contrib = {
url = "github:IvanMalison/xmonad-contrib/withMyChanges";
xmonad = {
url = path:./xmonad;
inputs.nixpkgs.follows = "nixpkgs";
inputs.xmonad.follows = "xmonad";
};
};
outputs = { self, flake-utils, nixpkgs, xmonad, xmonad-contrib, git-ignore-nix }:
outputs = { self, flake-utils, nixpkgs, xmonad, xmonad-contrib }:
let
overlay = import ./overlay.nix;
overlays = [ overlay xmonad.overlay xmonad-contrib.overlay ];

View File

@@ -1019,7 +1019,7 @@ addKeys conf@XConfig { modMask = modm } =
-- Non-XMonad
, ((modm, xK_v), spawn "xclip -o | xdotool type --file -")
, ((hyper, xK_v), spawn "rofi -modi 'clipboard:greenclip print' -show clipboard")
, ((hyper, xK_v), spawn "rofi_clipit.sh")
, ((hyper, xK_p), spawn "rofi-pass")
, ((hyper, xK_h), spawn "rofi_shutter")
, ((hyper, xK_c), spawn "shell_command.sh")

View File

@@ -9,7 +9,6 @@
.tern-port
.tutor
/eln-cache
/elpaca
/transient
/tree-sitter
README.el

View File

@@ -1,6 +1,6 @@
# -*- mode: org; -*-
[[https://github.com/IvanMalison/dotfiles/actions/workflows/gh-pages.yml][
file:https://github.com/IvanMalison/dotfiles/actions/workflows/gh-pages.yml/badge.svg?branch=master]]
[[https://travis-ci.org/IvanMalison/dotfiles][
file:https://travis-ci.org/IvanMalison/dotfiles.svg?branch=master]]
This document is best read at [[http://ivanmalison.github.io/dotfiles/]] or, of
course, in emacs, as the internal links that follow are unlikely to work
@@ -17,10 +17,18 @@ These sections are the ones that have the most potential to be interesting to
others:
** How I generate http://ivanmalison.github.io/dotfiles/
*** org-export
**** GitHub Actions
**** travis-ci
[[https://github.com/IvanMalison/dotfiles/tree/master/gen-gh-pages][This directory]] contains a collection of scripts that export this org document
to html. A [[https://github.com/IvanMalison/dotfiles/blob/master/.github/workflows/gh-pages.yml][GitHub Actions workflow]] runs on every push to master, generating the
HTML and deploying it to GitHub Pages.
to html. This approach is taken (with only a few modifications) from [[https://gist.github.com/domenic/ec8b0fc8ab45f39403dd][here]].
**** githook (The old way)
NOTE: I've left this here in case other people have an interest in this method,
but I no longer use it.
I wrote a [[https://github.com/IvanMalison/dotfiles/tree/9e56ced1dd70e50e1026aca5af51437e93add026/dotfiles/emacs.d/bin][githook and an installer script]] that automatically update index.html
at the root of the repository by running ~org-html-export-to-html~ on my
README.org (essentially this document) . These should work no matter where they
are placed in a repository. The org-mode file that they target is set [[https://github.com/IvanMalison/dotfiles/blob/16a4f6c3aadef39a45d30c15e8637b40858721ea/dotfiles/emacs.d/bin/util.sh#L4][here]] and
should be relatively easy to change.
*** [[https://github.com/fniessen/org-html-themes][Read The Org]]
I use [[https://github.com/fniessen][fniessen]]'s ReadTheOrg theme which can be found at
https://github.com/fniessen/org-html-themes.
@@ -163,9 +171,8 @@ startup as possible.
#+BEGIN_SRC emacs-lisp
(defvar imalison:do-benchmark)
(when user-init-file
(let ((bench-file (concat (file-name-directory user-init-file) "benchmark.el")))
(when (file-exists-p bench-file) (load bench-file))))
(let ((bench-file (concat (file-name-directory user-init-file) "benchmark.el")))
(when (file-exists-p bench-file) (load bench-file)))
(use-package benchmark-init
:if imalison:do-benchmark
@@ -231,7 +238,6 @@ Sets environment variables by starting a shell.
** noflet
#+BEGIN_SRC emacs-lisp
(use-package noflet
:after (dash) ;;@HACK: noflet does not properly declare dependencies
:demand t)
#+END_SRC
** Non-Forking Shell Command To String
@@ -317,41 +323,63 @@ I want to control my own font for emacs
* Functions
** Join Paths
Works in the same way as os.path.join in python
#+NAME: imalison-join-paths
#+BEGIN_SRC emacs-lisp :tangle no
#+BEGIN_SRC emacs-lisp
(defun imalison:join-paths (root &rest dirs)
(let ((result root))
(cl-loop for dir in dirs do
(setq result (concat (file-name-as-directory result) dir)))
result))
#+END_SRC
#+BEGIN_SRC emacs-lisp :noweb yes
<<imalison-join-paths>>
#+END_SRC
** Variables
#+NAME: imalison-projects-directory
#+BEGIN_SRC emacs-lisp :tangle no
#+BEGIN_SRC emacs-lisp
(defvar imalison:projects-directory
(imalison:join-paths (substitute-in-file-name "$HOME") "Projects"))
#+END_SRC
#+BEGIN_SRC emacs-lisp :noweb yes
<<imalison-projects-directory>>
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle org-config-bootstrap.el :noweb yes
<<imalison-join-paths>>
<<imalison-projects-directory>>
;; For org-config-bootstrap: frame-mode not needed in server/container context
(defvar imalison:use-frame-mode nil)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defvar imalison:gpg-key)
#+END_SRC
** Required Packages
The packages in this section provide no functionality on their own,
but provide support for writing custom elisp.
*** s
#+BEGIN_SRC emacs-lisp
(use-package s :demand t)
#+END_SRC
*** dash
#+BEGIN_SRC emacs-lisp
(use-package dash
:demand t
:config
(progn
(dash-enable-font-lock)))
#+END_SRC
*** gh
#+BEGIN_SRC emacs-lisp
(use-package gh
:defer t
:straight (gh :type git :host github :repo "IvanMalison/gh.el"))
#+END_SRC
*** shut-up
#+BEGIN_SRC emacs-lisp
(use-package shut-up
:config
(defun imalison:shut-up-around (function &rest args)
(shut-up (apply function args))))
#+END_SRC
*** parse-csv
#+BEGIN_SRC emacs-lisp
(use-package parse-csv
:demand t)
#+END_SRC
*** emit
#+BEGIN_SRC emacs-lisp
(use-package emit
:straight (emit :type git :host github :repo "colonelpanic8/emit"))
#+END_SRC
*** request
#+BEGIN_SRC emacs-lisp
(use-package request
:defer t)
#+END_SRC
** Named Build
<<namedbuild>>
imalison:named-build provides a way to invoke a macro in such a way
@@ -726,14 +754,8 @@ A macro for composing functions together to build an interactive command to copy
#+END_SRC
*** Copy portions of the buffer file name
#+BEGIN_SRC emacs-lisp
(defun imalison:buffer-file-name-or-directory ()
"Return `buffer-file-name' if available, otherwise `default-directory'.
This allows copy functions to work with buffers like magit that
aren't visiting a file but are associated with a directory."
(or buffer-file-name default-directory))
(defmacro imalison:copy-buffer-file-path-builder (&rest args)
`(imalison:compose-copy-builder ,@args imalison:buffer-file-name-or-directory))
`(imalison:compose-copy-builder ,@args buffer-file-name))
(imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-path-full)
(imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-name
@@ -834,7 +856,6 @@ details.
(directory-files filepath))))
(use-package eshell
:ensure nil
:commands (eshell-parse-colon-path imalison:get-executables-on-path)
:config
(defun imalison:get-executables-on-path ()
@@ -1117,15 +1138,8 @@ I keep it around just in case I need it.
*** frame-mode
#+BEGIN_SRC emacs-lisp
(defvar imalison:use-frame-mode
(let ((xdg-current (downcase (or (getenv "XDG_CURRENT_DESKTOP") "")))
(xdg-session (downcase (or (getenv "XDG_SESSION_DESKTOP") "")))
(desktop-session (downcase (or (getenv "DESKTOP_SESSION") ""))))
(or (getenv "HYPRLAND_INSTANCE_SIGNATURE")
(s-contains? "hyprland" xdg-current)
(s-contains? "hyprland" xdg-session)
(s-contains? "hyprland" desktop-session)
(and (executable-find "wmctrl")
(s-contains? "xmonad" (shell-command-to-string "wmctrl -m"))))))
(or (s-contains? "xmonad" (shell-command-to-string "wmctrl -m"))
(s-contains? "Hyprland" (shell-command-to-string "wmctrl -m"))))
(use-package frame-mode
:if imalison:use-frame-mode
@@ -1136,6 +1150,10 @@ I keep it around just in case I need it.
(frame-mode +1)
(frame-keys-mode +1)))
#+END_SRC
*** Handle xrefs annoying dedicated window garbage
#+BEGIN_SRC emacs-lisp
(use-package xref)
#+END_SRC
** Fill Setup
Get rid of nags about requiring setences to end with two spaces.
#+BEGIN_SRC emacs-lisp
@@ -1216,7 +1234,6 @@ This makes ~forward-word~ and ~backward-word~ understand snake and camel case.
proced is an top like utility that runs inside of emacs. The following sets auto updating automatically and makes the update interval faster.
#+BEGIN_SRC emacs-lisp
(use-package proced
:ensure nil
:defer t
:config
(progn
@@ -1360,7 +1377,6 @@ Paradox is a package.el extension. I have no use for it now that I use straight.
** server
#+BEGIN_SRC emacs-lisp
(use-package server
:ensure nil
:demand t
:config
(progn
@@ -1432,7 +1448,6 @@ The file server file for this emacs instance no longer exists.")
** winner
#+BEGIN_SRC emacs-lisp
(use-package winner
:ensure nil
:commands (winner-undo winner-redo)
:bind ("C-c q" . imalison:winner-hydra/body)
:config
@@ -1443,6 +1458,15 @@ The file server file for this emacs instance no longer exists.")
("n" winner-redo "forward" :exit t))
(winner-mode 1)))
#+END_SRC
** eyebrowse
I don't have any use for this now that I use frames mode, but its an interesting idea.
#+BEGIN_SRC emacs-lisp
(use-package eyebrowse
:disabled t
:defer 1
:config
(progn (eyebrowse-mode +1)))
#+END_SRC
** stream
#+BEGIN_SRC emacs-lisp
(use-package stream :defer t)
@@ -1495,9 +1519,9 @@ https://github.com/alpaker/Fill-Column-Indicator/issues/21 for more details
#+begin_src emacs-lisp
(use-package indent-bars
:disabled t
:ensure (indent-bars :type git :host github :repo "jdtsmith/indent-bars")
:straight (indent-bars :type git :host github :repo "jdtsmith/indent-bars")
:config
(require 'indent-bars-ts)
(require 'indent-bars-ts) ; not needed with straight
:custom
(indent-bars-treesit-support t)
(indent-bars-treesit-ignore-blank-lines-types '("module"))
@@ -1517,7 +1541,6 @@ fixes that, but for now, it needs to be run manually, since I haven't figured
out how to detect that a buffer is a man mode buffer.
#+BEGIN_SRC emacs-lisp
(use-package man
:ensure nil
:config
(progn
(defun imalison:fontify-man-page-buffer ()
@@ -1588,6 +1611,10 @@ out how to detect that a buffer is a man mode buffer.
(progn
(global-set-key (kbd "<escape>") 'god-local-mode)))
#+END_SRC
** bind-key
#+BEGIN_SRC emacs-lisp
(use-package bind-key)
#+END_SRC
** which-key
#+BEGIN_SRC emacs-lisp
(use-package which-key
@@ -1725,7 +1752,6 @@ bind-key and global-set-key forms.
** xref
#+begin_src emacs-lisp
(use-package xref
:ensure nil
:bind ("M-," . xref-go-back))
#+end_src
* Navigation
@@ -1740,7 +1766,6 @@ bind-key and global-set-key forms.
#+END_SRC
** projectile
#+BEGIN_SRC emacs-lisp
(use-package projectile
:demand t
:bind (:map projectile-mode-map
@@ -1754,7 +1779,7 @@ bind-key and global-set-key forms.
(projectile-git-submodule-command nil)
(project-vc-merge-submodules nil)
(projectile-current-project-on-switch 'keep))
:config
:preface
(progn
(defmacro imalison:projectile-do-in-project (project-dir &rest forms)
`(imalison:with-default-directory ,project-dir
@@ -1857,6 +1882,12 @@ bind-key and global-set-key forms.
:config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
:bind ("C-c w" . imalison:ace-window))
#+END_SRC
** neotree
Neotree is useless with frame mode for now, so I've disabled it.
#+BEGIN_SRC emacs-lisp
(use-package neotree
:disabled t)
#+END_SRC
** flimenu
#+BEGIN_SRC emacs-lisp
(use-package flimenu
@@ -1876,29 +1907,39 @@ bind-key and global-set-key forms.
#+begin_src emacs-lisp
(use-package vertico
:demand t
:bind (:map vertico-map
("TAB" . embark-act))
:config
(vertico-mode))
(use-package vertico-directory :ensure nil
:after (vertico)
:bind (:map vertico-map
("RET" . vertico-directory-enter)
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word))
:config)
(use-package vertico-grid :ensure nil :after (vertico))
(use-package vertico-buffer :ensure nil :after (vertico))
(use-package vertico-flat :ensure nil :after (vertico))
(use-package vertico-multiform :ensure nil :after (vertico)
:config
(progn
(vertico-multiform-mode +1)
(setq vertico-multiform-commands
'((consult-imenu grid)
(consult-ripgrep buffer)))))
(defmacro imalison:use-vertico-extension (extension-name &rest forms)
(let ((extension-symbol (intern (concat "vertico-" (symbol-name extension-name)))))
`(use-package ,extension-symbol
:after vertico
:straight (,extension-symbol
:repo "emacs-straight/vertico"
:host github
:files ,(list (concat "extensions/" (symbol-name extension-symbol) ".el")))
,@forms)))
(put 'imalison:use-vertico-extension 'lisp-indent-function 'defun)
(imalison:use-vertico-extension directory
:bind (:map vertico-map
("RET" . vertico-directory-enter)
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word)
("TAB" . embark-act)))
(imalison:use-vertico-extension grid)
(imalison:use-vertico-extension buffer)
(imalison:use-vertico-extension flat)
(imalison:use-vertico-extension multiform
:config
(progn
(vertico-multiform-mode +1)
(setq vertico-multiform-commands
'((consult-imenu grid)
(consult-ripgrep buffer)))))
(vertico-mode +1)))
#+end_src
** orderless
#+begin_src emacs-lisp
@@ -2018,6 +2059,22 @@ bind-key and global-set-key forms.
:config
(company-flx-mode +1))
#+END_SRC
** auto-complete
I don't use auto-complete at all, so I have set up a hook to automatically disable it whenever it is enabled to avoid creating conflicting popups when company is activated.
#+BEGIN_SRC emacs-lisp
(use-package auto-complete
:defer t
:preface
(progn
(defun imalison:auto-complete-hook ()
(debug)
(warn "auto-complete-mode was activated, but is being automatically disabled.")
(let ((auto-complete-mode-hook nil))
(auto-complete-mode -1))))
:config
(progn
(add-hook 'auto-complete-mode-hook 'imalison:auto-complete-hook)))
#+END_SRC
* Text Manipulation
** smartparens
#+BEGIN_SRC emacs-lisp
@@ -2165,7 +2222,6 @@ bind-key and global-set-key forms.
** align
#+BEGIN_SRC emacs-lisp
(use-package align
:ensure nil
:bind ("C-c C-a" . imalison:align-regexp-hydra/body)
:config
(progn
@@ -2213,10 +2269,16 @@ bind-key and global-set-key forms.
(global-flycheck-mode))
:diminish flycheck-mode)
#+END_SRC
* straight
#+BEGIN_SRC emacs-lisp
(use-package straight
:config
(setq straight-vc-git-auto-fast-forward t))
#+END_SRC
* auth-source
#+begin_src emacs-lisp
(use-package auth-source
:ensure nil
:straight nil
:config
(progn
(setq auth-sources '("~/.authinfo.gpg"))))
@@ -2230,7 +2292,6 @@ bind-key and global-set-key forms.
(defvar imalison:use-lsp-python t)
(use-package python
:ensure nil
:commands python-mode
:mode ("\\.py\\'" . python-mode)
:preface
@@ -2266,11 +2327,9 @@ bind-key and global-set-key forms.
*** ruby
#+begin_src emacs-lisp
(use-package ruby-mode
:ensure nil
:config
(with-eval-after-load 'apheleia
(setf (alist-get 'ruby-ts-mode apheleia-mode-alist)
'(rubocop))))
(setf (alist-get 'ruby-ts-mode apheleia-mode-alist)
'(rubocop)))
#+end_src
*** go
#+BEGIN_SRC emacs-lisp
@@ -2421,7 +2480,6 @@ it's supposed to do, but instead uses its own collection of functions to control
where the definition is popped up. This fixes that.
#+BEGIN_SRC emacs-lisp
(use-package find-func
:ensure nil
:preface
(progn
(defun imalison:find-function-display-buffer (function)
@@ -2441,6 +2499,14 @@ Macrostep is an indespensible tool for writing emacs lisp macros. It lets you se
:bind (:map lisp-mode-shared-map
("C-c e" . macrostep-expand)))
#+END_SRC
**** emr
#+BEGIN_SRC emacs-lisp
(use-package emr
:bind ("M-RET" . emr-show-refactor-menu)
:config
(progn
(add-hook 'prog-mode-hook 'emr-initialize)))
#+END_SRC
**** Editing configuration
Reduce indentation for some functions
#+BEGIN_SRC emacs-lisp
@@ -2454,7 +2520,6 @@ Reduce indentation for some functions
**** edebug
#+BEGIN_SRC emacs-lisp
(use-package edebug
:ensure nil
:defer t
:config
(progn (setq edebug-trace t)))
@@ -2535,7 +2600,7 @@ eval-last-sexp.
(check-parens)))
(defun imalison:emacs-lisp-hook ()
(when (fboundp 'elisp-slime-nav-mode) (elisp-slime-nav-mode t))
(elisp-slime-nav-mode t)
(add-hook 'write-file-functions 'imalison:maybe-check-parens nil t))
(add-hook 'emacs-lisp-mode-hook 'imalison:emacs-lisp-hook)
@@ -2577,7 +2642,7 @@ eval-last-sexp.
(setq nix-indent-function 'nix-indent-line)))
(use-package lsp-nix
:ensure nil
:straight nil
:after (lsp-mode)
:config
(progn
@@ -2651,8 +2716,6 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
#+END_SRC
**** clj-refactor
#+BEGIN_SRC emacs-lisp
;;@WORKAROUND clj-refactor dependency inflections Version metadata
(use-package inflections :ensure (:depth nil :version elpaca-latest-tag :version-regexp "[[:digit:]]\\.[[:digit:]]"))
(use-package clj-refactor
:commands clj-refactor-mode)
#+END_SRC
@@ -2818,9 +2881,10 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
(use-package purty
:commands purty-on-save-mode
:ensure (purty :repo "joneshf/purty"
:host gitlab
:files ("purty.el")))
:straight (purty :repo "joneshf/purty"
:type git
:host gitlab
:files ("purty.el")))
(use-package psc-ide
:after purescript-mode
@@ -2858,7 +2922,7 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
#+END_SRC
*** C/C++
#+BEGIN_SRC emacs-lisp
(use-package cc-mode :ensure nil :defer t)
(use-package cc-mode)
#+END_SRC
*** C--
#+BEGIN_SRC emacs-lisp
@@ -2945,19 +3009,13 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
*** org
My org-mode configuration now lives in its own file org-config.org.
#+BEGIN_SRC emacs-lisp
(let* ((org-config (expand-file-name "org-config.org" user-emacs-directory))
(org-config-el (expand-file-name "org-config.el" user-emacs-directory)))
(when (file-newer-than-file-p org-config org-config-el)
;; Tangle all outputs so org-config-bind.el/org-config-config.el are fresh.
(org-babel-tangle-file org-config)
(when (file-exists-p org-config-el)
(set-file-times org-config-el)))
(load-file org-config-el))
(org-babel-load-file
(concat (file-name-directory load-file-name) "org-config.org"))
#+END_SRC
*** TeX
#+BEGIN_SRC emacs-lisp
(use-package tex
:ensure (auctex :host github :repo "raxod502/auctex"
:straight (auctex :host github :repo "raxod502/auctex"
:branch "fork/1"
:files (:defaults (:exclude "doc/*.texi")))
:commands TeX-mode
@@ -2982,7 +3040,7 @@ My org-mode configuration now lives in its own file org-config.org.
**** latex
#+BEGIN_SRC emacs-lisp
(use-package latex
:ensure nil
:straight auctex
:after tex
:config
(progn
@@ -3131,7 +3189,6 @@ My org-mode configuration now lives in its own file org-config.org.
** vc
#+begin_src emacs-lisp
(use-package vc
:ensure nil
:config
(progn
(defun vc-find-revision-of-file (revision)
@@ -3278,7 +3335,6 @@ emr (emacs refactor) provides support for refactoring in many programming langua
** semantic
#+BEGIN_SRC emacs-lisp
(use-package semantic
:ensure nil
:commands semantic-mode
:disabled t
:preface
@@ -3341,7 +3397,6 @@ in term-mode. This makes term-mode 1000% more useful
(especially having M-x and C-y available).
#+BEGIN_SRC emacs-lisp
(use-package term
:ensure nil
:demand t
:preface
(progn
@@ -3419,8 +3474,8 @@ in term-mode. This makes term-mode 1000% more useful
(progn
(use-package term-manager-eat
:demand t
:ensure
(term-manager-eat :files ("term-manager-eat.el")
:straight
(term-manager-eat :type git :files ("term-manager-eat.el")
:host github :repo "colonelpanic8/term-manager"))
(setq term-projectile-term-manager (term-projectile :build-term 'term-manager-eat-build-term))
(emit-prefix-selector imalison:term
@@ -3517,6 +3572,15 @@ crux-reopen-as-root-mode makes it so that any file owned by root will automatica
(setq gptel-model "gpt-4")
))
#+end_src
** claude-code-ide
#+begin_src emacs-lisp
(use-package claude-code-ide
:straight (:type git :host github :repo "manzaltu/claude-code-ide.el")
:bind ("C-c C-'" . claude-code-ide-menu)
:config
(claude-code-ide-emacs-tools-setup)
(setq claude-code-ide-terminal-backend 'eat))
#+end_src
* Cooperation
** togetherly
#+BEGIN_SRC emacs-lisp
@@ -3554,17 +3618,23 @@ crux-reopen-as-root-mode makes it so that any file owned by root will automatica
(define-key isearch-mode-map [remap isearch-query-replace-regexp]
#'anzu-isearch-query-replace-regexp)))
#+END_SRC
** shell-history
I think that shell-history is causing projectile to be very slow so I have disabled it.
#+BEGIN_SRC emacs-lisp
(use-package shell-history
:demand t
:disabled t)
#+END_SRC
** iedit
I don't use iedit directly, but it is used by [[*emr][emr]] and I need to disable ~iedit-toggle-key-default~ or else a buffer pops up complaing that the key has been bound to something else
#+BEGIN_SRC emacs-lisp
;;@WORKAROUND iedit has oddball version scheme. Report upstream bug.
(use-package iedit :ensure (:depth nil :version (lambda (_) "0.99"))
(use-package iedit
:defer t)
#+END_SRC
** tramp
#+BEGIN_SRC emacs-lisp
(use-package tramp
:ensure nil
:straight nil
:commands tramp
:config
(setq tramp-default-method "scp"))
@@ -3572,8 +3642,6 @@ I don't use iedit directly, but it is used by [[*emr][emr]] and I need to disabl
** narrow-indirect
#+BEGIN_SRC emacs-lisp
(use-package narrow-indirect
:disabled t ;;@FIX where is it hosted? locally? add :ensure nil + use-package :load-path keyword
:ensure nil
:init
(progn
(define-key ctl-x-4-map "nd" 'ni-narrow-to-defun-indirect-other-window)
@@ -3629,7 +3697,6 @@ I had to disable this mode because something that it does messes with coding set
** recentf
#+BEGIN_SRC emacs-lisp
(use-package recentf
:ensure nil
:demand t
:config
(progn
@@ -3668,7 +3735,7 @@ I have currently disabled key-chord because it may cause typing lag.
** calc-mode
#+BEGIN_SRC emacs-lisp
(use-package calc-mode
:ensure nil
:straight nil
:commands calc
:config
(progn
@@ -3725,7 +3792,6 @@ Not really sure what this is
** epg
#+BEGIN_SRC emacs-lisp
(use-package epg
:ensure nil
:after shut-up
:config
(shut-up
@@ -3738,6 +3804,124 @@ Not really sure what this is
:config
(pinentry-start))
#+END_SRC
** twittering-mode
#+BEGIN_SRC emacs-lisp
(use-package twittering-mode
:commands twittering-mode)
#+END_SRC
** matrix-client
#+BEGIN_SRC emacs-lisp
(use-package matrix-client
:disabled t ;; fails to load eieio on startup
)
#+END_SRC
** mu4e
#+BEGIN_SRC emacs-lisp
;; (eval-when-compile
;; (require 's)
;; (defvar mu4e-elisp-directory
;; (s-trim (shell-command-to-string "mu4e_directory"))))
(use-package mu4e
:disabled t
:load-path mu4e-elisp-directory
:straight nil
:commands (mu4e mu4e-view-message-with-msgid mu4e-update-index email)
:bind ("C-c 0" . email)
:config
(progn
(defun email (&optional arg)
(interactive "P")
(if (string-equal (persp-name persp-curr) "email")
(progn (delete-other-windows) (mu4e))
(progn
(persp-switch "email")
(when (or (not (mu4e-running-p)) arg)
(delete-other-windows) (mu4e)))))
;; enable inline images
(setq mu4e-view-show-images t)
;; show images
(setq mu4e-show-images t)
;; Try to display html as text
(setq mu4e-view-prefer-html nil)
(setq mu4e-html2text-command "html2text -width 80 -nobs -utf8")
;; use imagemagick, if available
(when (fboundp 'imagemagick-register-types)
(imagemagick-register-types))
(setq mail-user-agent 'mu4e-user-agent)
(require 'org-mu4e)
(setq mu4e-compose-complete-only-after nil)
(setq mu4e-maildir "~/Mail")
(setq mu4e-drafts-folder "/[Gmail].Drafts")
(setq mu4e-sent-folder "/[Gmail].Sent Mail")
(setq mu4e-trash-folder "/[Gmail].Trash")
(setq mu4e-sent-messages-behavior 'delete)
(setq mu4e-headers-skip-duplicates t)
(setq mu4e-update-interval (* 60 20))
(setq message-kill-buffer-on-exit t)
(setq mail-user-agent 'mu4e-user-agent) ;; make mu4e the default mail client
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
(setq mu4e-sent-messages-behavior 'delete)
;; allow for updating mail using 'U' in the main view:
(setq mu4e-get-mail-command "timeout 60 offlineimap")
(add-hook 'mu4e-compose-mode-hook
(defun my-do-compose-stuff () (flyspell-mode)))
(add-to-list 'mu4e-headers-actions '("view in browser" . mu4e-action-view-in-browser))
(add-to-list 'mu4e-view-actions '("view in browser" . mu4e-action-view-in-browser))
(defun mu4e-view (msg headersbuf)
"Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
'In sync' here means that moving to the next/previous message in
the the message view affects HDRSBUF, as does marking etc.
As a side-effect, a message that is being viewed loses its 'unread'
marking if it still had that."
(let* ((embedded ;; is it as an embedded msg (ie. message/rfc822 att)?
(when (gethash (mu4e-message-field msg :path)
mu4e~path-parent-docid-map) t))
(buf
(if embedded
(mu4e~view-embedded-winbuf)
(get-buffer-create mu4e~view-buffer-name))))
;; note: mu4e~view-mark-as-read will pseudo-recursively call mu4e-view again
;; by triggering mu4e~view again as it marks the message as read
(with-current-buffer buf
(switch-to-buffer buf)
(setq mu4e~view-msg msg)
;;(or embedded (not (mu4e~view-mark-as-read msg)))
(when (or (mu4e~view-mark-as-read msg) t)
(let ((inhibit-read-only t))
(erase-buffer)
(mu4e~delete-all-overlays)
(insert (mu4e-view-message-text msg))
(goto-char (point-min))
(mu4e~fontify-cited)
(mu4e~fontify-signature)
(mu4e~view-make-urls-clickable)
(mu4e~view-show-images-maybe msg)
(setq
mu4e~view-buffer buf
mu4e~view-headers-buffer headersbuf)
(when embedded (local-set-key "q" 'kill-buffer-and-window))
(mu4e-view-mode))))))
(require 'smtpmail)
;; alternatively, for emacs-24 you can use:
(setq message-send-mail-function 'smtpmail-send-it
smtpmail-stream-type 'starttls
smtpmail-default-smtp-server "smtp.gmail.com"
smtpmail-smtp-server "smtp.gmail.com"
smtpmail-smtp-service 587)))
#+END_SRC
** gmail-message-mode
This is useful with server mode when editing gmail messages. I think that it is not currently working, or it may need to be manually enabled.
#+BEGIN_SRC emacs-lisp
@@ -3782,7 +3966,7 @@ This is useful with server mode when editing gmail messages. I think that it is
(progn
(when (eq system-type 'darwin)
(setq sauron-modules '(sauron-erc sauron-org sauron-notifications
sauron-jabber sauron-identica))
sauron-twittering sauron-jabber sauron-identica))
(defun sauron-dbus-start ()
nil)
(makunbound 'dbus-path-emacs)))
@@ -3801,11 +3985,14 @@ This is useful with server mode when editing gmail messages. I think that it is
(defun sauron:erc-notify (origin priority message &optional properties)
(let ((event (plist-get properties :event)))
(funcall notify-function "IRC" message)))
(defun sauron:mu4e-notify (origin priority message &optional properties)
nil)
(defun sauron:dbus-notify (origin priority message &optional properties)
(funcall notify-function "GMail" message))
(defun sauron:dispatch-notify (origin priority message &optional properties)
(let ((handler (cond ((string= origin "erc") 'sauron:erc-notify)
((string= origin "jabber") 'sauron:jabber-notify)
((string= origin "mu4e") 'sauron:mu4e-notify)
((string= origin "dbus") 'sauron:dbus-notify)
(t (lambda (&rest r) nil)))))
(funcall handler origin priority message properties)))
@@ -3817,7 +4004,6 @@ This is useful with server mode when editing gmail messages. I think that it is
** screenshot
#+BEGIN_SRC emacs-lisp
(use-package screenshot
:disabled t ;;@FIX :ensure (:host github :repo "tecosaur/screenshot")?
:commands screenshot)
#+END_SRC
** libmpdee
@@ -3828,7 +4014,6 @@ This is useful with server mode when editing gmail messages. I think that it is
** flyspell
#+BEGIN_SRC emacs-lisp
(use-package flyspell
:ensure nil
:disabled t ; kind of annoying
:preface (setq flyspell-issue-welcome-flag nil)
:config
@@ -3879,6 +4064,55 @@ This is useful with server mode when editing gmail messages. I think that it is
("gtl" . "\\.cql\\'")))))
#+END_SRC
** perspective
I've disabled perspective because I just don't use it much.
#+BEGIN_SRC emacs-lisp
(use-package perspective
:disabled t
:demand t
:config
(progn
(persp-mode)
(defun persp-get-perspectives-for-buffer (buffer)
"Get the names of all of the perspectives of which `buffer` is a member."
(cl-loop for perspective being the hash-value of perspectives-hash
if (member buffer (persp-buffers perspective))
collect (persp-name perspective)))
(defun persp-pick-perspective-by-buffer (buffer)
"Select a buffer and go to the perspective to which that buffer
belongs. If the buffer belongs to more than one perspective
completion will be used to pick the perspective to switch to.
Switch the focus to the window in which said buffer is displayed
if such a window exists. Otherwise display the buffer in whatever
window is active in the perspective."
(interactive (list (funcall persp-interactive-completion-function
"Buffer: " (mapcar 'buffer-name (buffer-list)))))
(let* ((perspectives (persp-get-perspectives-for-buffer (get-buffer buffer)))
(perspective (if (> (length perspectives) 1)
(funcall persp-interactive-completion-function
(format "Select the perspective in which you would like to visit %s."
buffer)
perspectives)
(car perspectives))))
(if (string= (persp-name persp-curr) perspective)
;; This allows the opening of a single buffer in more than one window
;; in a single perspective.
(switch-to-buffer buffer)
(progn
(persp-switch perspective)
(if (get-buffer-window buffer)
(set-frame-selected-window nil (get-buffer-window buffer))
(switch-to-buffer buffer))))))
(defun persp-mode-switch-buffers (arg)
(interactive "P")
(if arg (call-interactively 'ido-switch-buffer)
(call-interactively 'persp-pick-perspective-by-buffer)))
(define-key persp-mode-map (kbd "C-x b") 'persp-mode-switch-buffers))
:bind ("C-c 9" . persp-switch))
#+END_SRC
** android-mode
#+BEGIN_SRC emacs-lisp
(use-package android-mode
@@ -3902,20 +4136,17 @@ This also adds syntax highlighting for gradle
** jsx-mode
#+BEGIN_SRC emacs-lisp
(use-package jsx-mode
:disabled t ;;@FIX Add :ensure with package recipe. Could not find "jsx-mode" hosted anywhere
:defer t)
#+END_SRC
** css
#+BEGIN_SRC emacs-lisp
(use-package css-mode
:ensure nil
:mode (("\\.css\\'" . css-mode)
("\\.rasi\\'" . css-mode)))
#+END_SRC
** sgml-mode
#+BEGIN_SRC emacs-lisp
(use-package sgml-mode
:ensure nil
;; :bind ("C-c b" . web-beautify-html) TODO: mode specific, change binding
:commands sgml-mode)
#+END_SRC
@@ -3949,13 +4180,13 @@ Ensure all themes that I use are installed:
(defvar-setq packages-appearance
'(monokai-theme zenburn-theme base16-theme molokai-theme moe-theme
tango-2-theme gotham-theme sublime-themes
tango-2-theme gotham-theme sublime-themes rainbow-delimiters
waher-theme ample-theme material-theme zerodark-theme
color-theme-modern leuven-theme spacemacs-theme gruvbox-theme
forest-blue-theme flatland-theme afternoon-theme
cyberpunk-theme dracula-theme))
(mapcar #'elpaca-try packages-appearance)
(mapcar 'straight-use-package packages-appearance)
(use-package doom-themes
:defer t)
@@ -3967,15 +4198,9 @@ Ensure all themes that I use are installed:
(use-package all-the-icons
:demand t)
#+END_SRC
** nerd-icons
#+BEGIN_SRC emacs-lisp
(use-package nerd-icons
:demand t)
#+END_SRC
** doom-modeline
#+begin_src emacs-lisp
(use-package doom-modeline
:after nerd-icons
:commands doom-modeline-mode
:custom
(doom-modeline-height 40))
@@ -4122,7 +4347,8 @@ load-theme hook (See the heading below).
(setq imalison:default-font-size-pt (face-attribute 'default :height))
(setq imalison:appearance-setup-done t)))
(add-hook 'elpaca-after-init-hook 'imalison:appearance-setup-hook)
(add-hook 'after-make-frame-functions 'imalison:appearance-setup-hook)
(add-hook 'after-init-hook 'imalison:appearance-setup-hook)
#+END_SRC
* Post Init Custom
#+BEGIN_SRC emacs-lisp

View File

@@ -1,39 +0,0 @@
;; Elpaca Installer -*- lexical-binding: t; -*-
(defvar elpaca-installer-version 0.11)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1 :inherit ignore
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (<= emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let* ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))

View File

@@ -1,19 +1,49 @@
;; -*- no-byte-compile: t; lexical-binding: t; -*-
;; -*- no-byte-compile: t -*-
(let ((bootstrap-file (concat user-emacs-directory "straight/bootstrap.el"))
(bootstrap-version 2))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(setq native-comp-deferred-compilation-deny-list '("magit"))
(setq native-comp-always-compile t)
(setq load-no-native t)
(setq no-native-compile t)
(setq warning-minimum-level :emergency)
(setq straight-disable-native-compile t)
;; This is a workaround for an issue in emacs28 with symlinks. See https://github.com/radian-software/straight.el/issues/701
(defun my-patch-package-find-file-visit-truename (oldfun &rest r)
(let ((find-file-visit-truename nil))
(apply oldfun r)))
(advice-add #'straight--build-autoloads :around
#'my-patch-package-find-file-visit-truename)
(setq package-enable-at-startup nil
straight-use-package-by-default t
straight-vc-git-default-protocol 'ssh)
(straight-use-package 'use-package)
(require 'use-package)
(setq use-package-enable-imenu-support t)
(setq use-package-ensure-function 'straight-use-package-ensure-function)
(defvar imalison:do-benchmark nil)
(defun emacs-directory-filepath (filename)
(concat (file-name-directory load-file-name) filename))
(let ((bench-file (concat (file-name-directory user-init-file) "benchmark.el")))
(when (file-exists-p bench-file) (load bench-file)))
(load-file (expand-file-name "elpaca-installer.el" user-emacs-directory))
(elpaca elpaca-use-package (elpaca-use-package-mode))
(setq use-package-enable-imenu-support t)
(setq use-package-always-ensure t)
(use-package benchmark-init
:if imalison:do-benchmark
:demand t
:config
(setq max-specpdl-size 99999999))
(defvar imalison:kat-mode nil)
(setq custom-file "~/.emacs.d/custom-before.el")
@@ -25,81 +55,36 @@
(setq mac-option-modifier 'meta)
(setq mac-command-modifier 'super))
;;The packages in this section are used to as utilities in the rest of this init file.
;;Ensure they are installed/activated first.
(use-package s
:ensure (:wait t)
;; See https://github.com/magit/magit/discussions/4997 . Without this magit is broken.
(use-package magit
:demand t)
(use-package dash
:ensure (:wait t)
:demand t
:config
(progn (dash-enable-font-lock)))
(use-package gh
:defer t
:ensure (:host github :repo "IvanMalison/gh.el"))
(use-package shut-up
:config
(defun imalison:shut-up-around (function &rest args)
(shut-up (apply function args))))
(use-package parse-csv :demand t)
(use-package emit
:ensure (emit :type git :host github :repo "colonelpanic8/emit")
:demand t
:config
(progn
(emit-prefix-selector imalison:mark-ring mark-ring)
(emit-prefix-selector imalison:shell-command-on-region
imalison:copy-shell-command-on-region
imalison:shell-command-on-region-replace
imalison:jq-replace)
(defun imalison:jq-replace (start end)
(interactive (region-if-active-otherwise-buffer))
(imalison:shell-command-on-region-replace start end "jq ."))
(emit-compose
imalison:copy-eval-last-sexp kill-new prin1-to-string eval-last-sexp)
(emit-prefix-selector imalison:eval-last-sexp
eval-region-or-last-sexp
imalison:copy-eval-last-sexp)))
(use-package request :defer t)
;; This seems to fix issues with helm not explicitly declaring its dependency on async
(use-package async :demand t)
;; Without this, org can behave very strangely
(use-package org
:ensure
:straight
(org :type git :host github :repo "colonelpanic8/org-mode" :local-repo "org"
:branch "my-main-2025"
:depth full
:build (:not autoloads)
:files (:defaults "lisp/*.el" ("etc/styles/" "etc/styles/*"))
:wait t))
:depth full :pre-build (straight-recipes-org-elpa--build) :build
(:not autoloads) :files
(:defaults "lisp/*.el" ("etc/styles/" "etc/styles/*")))
:defer t)
(elpaca-wait)
;; Install transient early to prevent built-in version from loading
(use-package transient
:ensure (:host github :repo "magit/transient" :wait t)
:demand t)
(elpaca-wait)
(when (or (equal (s-trim (shell-command-to-string "whoami")) "kat")
imalison:kat-mode)
(let ((debug-on-error t))
(org-babel-load-file
(concat (file-name-directory load-file-name) "kat-mode.org"))))
(use-package dash :demand t)
(let ((debug-on-error t))
(org-babel-load-file
(expand-file-name "README.org" user-emacs-directory)))
(concat (file-name-directory load-file-name) "README.org")))
;; (when imalison:do-benchmark (benchmark-init/deactivate))
(when (or (equal (s-trim (shell-command-to-string "whoami")) "kat")
imalison:kat-mode)
(let ((debug-on-error t))
(org-babel-load-file
(concat (file-name-directory load-file-name) "kat-mode.org"))))
(when imalison:do-benchmark (benchmark-init/deactivate))
;; Local Variables:
;; flycheck-disabled-checkers: (emacs-lisp-checkdoc)

View File

@@ -90,7 +90,7 @@ This makes evil-mode play nice with org-fc
*** javascript
#+begin_src emacs-lisp
(use-package ob-js
:ensure nil
:straight nil
:after org
:config
(progn

View File

@@ -1,43 +1,91 @@
;;; org-api.el --- org-agenda-api server configuration -*- lexical-binding: t; -*-
;; Load main emacs config to get org settings, custom commands, etc.
(let ((current-dir (if load-file-name (file-name-directory load-file-name) "~/.emacs.d/")))
(load (expand-file-name "init.el" current-dir)))
;; Ensure dependencies are loaded
(use-package simple-httpd
:demand t)
(require 'simple-httpd)
(require 'org-agenda-api)
;; Configure capture templates for the API
;; These use the org-agenda-api format with :prompts for API parameters
(setq org-agenda-api-capture-templates
`(("gtd-todo"
:name "GTD Todo"
:template ("t" "Todo" entry (file "~/org/inbox.org")
(function (lambda ()
(imalison:make-org-todo-template :content "%^{Title}")))
:immediate-finish t)
:prompts (("Title" :type string :required t)))
("scheduled-todo"
:name "Scheduled Todo"
:template ("s" "Scheduled" entry (file "~/org/inbox.org")
"* TODO %^{Title}\nSCHEDULED: %^{When}t\n"
:immediate-finish t)
:prompts (("Title" :type string :required t)
("When" :type date :required t)))
("tagged-todo"
:name "Tagged Todo"
:template ("g" "Tagged" entry (file "~/org/inbox.org")
"* TODO %^{Title} %^{Tags}g\n"
:immediate-finish t)
:prompts (("Title" :type string :required t)
("Tags" :type tags :required nil)))))
(defun org-api-get-todo-elements-from-filepath (filepath)
(let ((todo-elements nil))
(with-current-buffer (find-file-noselect filepath)
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-todo-regexp nil t)
(let* ((element (org-element-at-point))
(type (org-element-type element)))
(when (eq type 'headline)
(let ((todo (org-element-property :todo-keyword element)))
(when todo
(push element todo-elements))))))))
todo-elements))
;; Configure the server
(setq org-agenda-api-port 2025)
(setq org-agenda-api-inbox-file "~/org/inbox.org")
(defun org-api-get-agenda-todos ()
(let* ((today (calendar-gregorian-from-absolute (org-today))))
(mapcan 'org-api-get-todo-elements-from-filepath org-agenda-files)))
;; Start the server
(message "Starting org-agenda-api server on port %d" org-agenda-api-port)
(org-agenda-api-start)
(message "org-agenda-api server started")
(defun org-api-get-element-json (element)
(let ((todo (org-element-property :todo-keyword element))
(title (org-element-property :raw-value element))
(tags (org-element-property :tags element))
(level (org-element-property :level element))
(scheduled (org-element-property :scheduled element))
(deadline (org-element-property :deadline element)))
`(("todo" . ,todo)
("title" . ,title)
("tags" . ,tags)
("level" . ,level)
("scheduled" . ,(when scheduled (org-format-timestamp scheduled "%Y-%m-%dT%H:%M:%SZ")))
("deadline" . ,(when deadline (org-format-timestamp deadline "%Y-%m-%dT%H:%M:%SZ"))))))
(defun org-api-item-json (item)
(let* ((todo (get-text-property 0 'todo-state item))
(title (substring-no-properties item))
(tags (get-text-property 0 'tags item))
(s (get-text-property 0 'ts-date item))
(scheduled (when s
(org-format-timestamp (org-time-from-absolute s) "%Y-%m-%dT%H:%M:%SZ") )))
`(("todo" . ,todo)
("title" . ,title)
("tags" . ,tags))))
(defun org-api-get-scheduled-or-deadlined (day filepath)
(with-current-buffer (find-file-noselect filepath)
(org-dlet ((date day))
(setf org-agenda-current-date date)
(nconc (org-agenda-get-deadlines) (org-agenda-get-scheduled)))))
(defun org-api-get-today-agenda ()
(let ((day (calendar-current-date)))
(mapcan (lambda (filepath) (org-api-get-scheduled-or-deadlined day filepath))
org-agenda-files)))
(defservlet get-all-todos application/json ()
(insert (json-encode (mapcar 'org-api-get-element-json (org-api-get-agenda-todos)))))
(defservlet get-todays-agenda application/json ()
(insert
(json-encode
(mapcar 'org-api-item-json
(org-api-get-today-agenda)))))
(defservlet create-todo application/json (a b c)
(org-api-capture (gethash "title" (json-parse-string (cadr (assoc "Content" c))))))
(cl-defun org-api-build-capture-template
(content &key (character "d") (heading "Dynamic"))
`(,character ,heading entry (file "~/org/inbox.org")
(function (lambda ()
(imalison:make-org-todo-template :content content)))
:immediate-finish t))
(defun org-api-capture (content)
(let* ((org-capture-templates (list (org-api-build-capture-template content))))
(org-capture nil "d")))
(message "Starting http server")
(setq httpd-port 2025)
(httpd-start)
(message "Finished starting http server")

View File

@@ -1,6 +1,6 @@
* include-file-as-forms
We're going to use this to write separate parts of our config to different sections that will then be provided to our use package statment
#+begin_src emacs-lisp :tangle org-config.el
#+begin_src emacs-lisp
(defun imalison:include-file-as-forms (filename)
"Include the contents of FILENAME into the source as s-expressions."
(with-temp-buffer
@@ -15,10 +15,9 @@ We're going to use this to write separate parts of our config to different secti
`,@(nreverse forms))))
#+end_src
* use-package
#+begin_src emacs-lisp :tangle org-config.el
#+begin_src emacs-lisp
(defmacro imalison:org-config ()
`(use-package org
:ensure nil
:commands (org-mode org org-mobile-push org-mobile-pull org-agenda)
:mode ("\\.org\\'" . org-mode)
:preface (progn ,@(imalison:include-file-as-forms (imalison:join-paths user-emacs-directory "org-config-preface.el")))
@@ -29,25 +28,9 @@ We're going to use this to write separate parts of our config to different secti
(imalison:org-config)
#+end_src
* My Customization Variables
#+begin_src emacs-lisp :tangle org-config.el
;; Load org-config-preface when org-config.el is loaded directly.
(let ((preface (expand-file-name "org-config-preface.el" user-emacs-directory)))
(when (file-exists-p preface)
(load-file preface)))
;; Fallbacks in case preface isn't available yet.
(unless (boundp 'imalison:org-dir)
(defvar imalison:org-dir "~/org"))
(unless (boundp 'imalison:created-property-string)
(defvar imalison:created-property-string "
:PROPERTIES:
:ID: %(org-id-new)
:CREATED: %U
:END:"))
#+end_src
#+begin_src emacs-lisp :tangle org-config-preface.el
(defvar imalison:org-dir "~/org")
(defvar imalison:shared-org-dir "~/org")
(defvar imalison:shared-org-dir "~/katnivan")
(defvar imalison:org-whoami "Ivan Malison")
(defvar imalison:org-people (list nil "Ivan Malison" "Kat Huang"))
(defvar imalison:org-people-associated-states
@@ -82,7 +65,7 @@ We're going to use this to write separate parts of our config to different secti
(defvar imalison:repeating-org-files
(list imalison:org-habits-file imalison:shared-habits-file imalison:shared-repeating-file))
(defvar imalison:include-repeating-in-agenda t)
(defvar imalison:include-repeating-in-agenda nil)
(defun imalison:add-to-org-agenda-files (incoming-files)
(setq org-agenda-files
@@ -93,7 +76,6 @@ We're going to use this to write separate parts of our config to different secti
(defvar imalison:created-property-string "
:PROPERTIES:
:ID: %(org-id-new)
:CREATED: %U
:END:")
#+end_src
@@ -114,7 +96,7 @@ We're going to use this to write separate parts of our config to different secti
#+end_src
* Org Variable Customization
#+begin_src emacs-lisp :tangle org-config-custom.el
(org-agenda-log-mode-items '(closed state))
(org-agenda-log-mode-items '(closed))
(org-agenda-skip-deadline-if-done t)
(org-agenda-skip-scheduled-if-done t)
(org-agenda-span 10)
@@ -222,35 +204,6 @@ We're going to use this to write separate parts of our config to different secti
((current-time (&rest args) time))
(funcall fn)))
#+end_src
** Reschedule Past Items to Today
This function finds all incomplete items in the agenda files that are scheduled
in the past and reschedules them to today. Useful for catching up on tasks that
have slipped past their original scheduled date.
#+begin_src emacs-lisp :tangle org-config-config.el
(defun imalison:reschedule-past-to-today ()
"Reschedule all incomplete items scheduled in the past to today.
Iterates through all org-agenda files and reschedules any TODO items
that have a SCHEDULED date before today to the current date."
(interactive)
(let* ((today-time (org-time-string-to-time (format-time-string "<%Y-%m-%d>")))
(rescheduled-count 0))
(org-map-entries
(lambda ()
(let* ((scheduled (org-entry-get nil "SCHEDULED"))
(scheduled-time (when scheduled (org-time-string-to-time scheduled))))
(when (and scheduled-time
(not (org-entry-is-done-p))
(time-less-p scheduled-time today-time))
(org-schedule nil ".")
(cl-incf rescheduled-count))))
nil
'agenda)
(message "Rescheduled %d items to today" rescheduled-count)))
#+end_src
#+RESULTS:
: imalison:reschedule-past-to-today
** Miscellaneous
#+begin_src emacs-lisp :tangle org-config-config.el
(add-to-list 'org-show-context-detail '(org-goto . lineage))
@@ -517,11 +470,7 @@ that have a SCHEDULED date before today to the current date."
(missing-priority
'(tags-todo "-PRIORITY={.}/!"
((org-agenda-overriding-header
"These don't have priorities:"))))
(high-priority-unscheduled
'(tags-todo "+PRIORITY<\"C\"-SCHEDULED={.}-DEADLINE={.}/!"
((org-agenda-overriding-header
"High priority without scheduled/deadline:")))))
"These don't have priorities:")))))
(setq org-agenda-custom-commands
`(("M" "Main agenda view"
@@ -550,12 +499,7 @@ that have a SCHEDULED date before today to the current date."
((org-agenda-overriding-header "Completion History:")
(org-agenda-ndays 5)
(org-agenda-entry-types '(:none))
(org-agenda-start-with-log-mode '(state)))))
,(cons "i" (cons "Inbox" inbox))
,(cons "n" (cons "Next" next))
("w" "Wait" todo "WAIT"
((org-agenda-overriding-header "Waiting:")))
,(cons "u" (cons "High priority unscheduled" high-priority-unscheduled)))))
(org-agenda-start-with-log-mode '(state))))))))
#+end_src
*** Filters
**** Regexp Presets
@@ -618,7 +562,6 @@ specific time, they should appear in the agenda at that time!
(with-temp-buffer
(org-mode)
(insert content)
(org-set-property "ID" (org-id-new))
(org-set-property "CREATED"
(with-temp-buffer
(org-insert-time-stamp
@@ -635,7 +578,6 @@ specific time, they should appear in the agenda at that time!
(org-insert-heading)
(insert content)
(org-todo creation-state)
(org-set-property "ID" (org-id-new))
(org-set-property "CREATED"
(with-temp-buffer
(org-insert-time-stamp
@@ -692,7 +634,7 @@ specific time, they should appear in the agenda at that time!
*** Templates
#+begin_src emacs-lisp :tangle org-config-config.el
(use-package org-capture
:ensure nil
:straight nil
:config
(add-to-list 'org-capture-templates
`("t" "GTD Todo (Linked)" entry (file ,imalison:org-gtd-file)
@@ -725,7 +667,6 @@ specific time, they should appear in the agenda at that time!
"* TODO
SCHEDULED: %^t
:PROPERTIES:
:ID: %(org-id-new)
:CREATED: %U
:STYLE: habit
:END:"))
@@ -736,14 +677,7 @@ SCHEDULED: %^t
(find-file (let ((date (format-time-string "%Y-%m-%d")))
(expand-file-name (concat date ".org")
"~/org/weekly")))))
(file "~/org/capture-templates/weekly.org")))
(add-to-list 'org-capture-templates
`("n" "Next (Scheduled Today)" entry (file ,imalison:org-gtd-file)
,(format "%s%s\n%s" "* NEXT %?" imalison:created-property-string
"SCHEDULED: %(format-time-string \"<%Y-%m-%d %a>\")")))
(add-to-list 'org-capture-templates
`("i" "Inbox" entry (file ,imalison:org-gtd-file)
(function (lambda (&rest args) (imalison:make-org-todo-template :creation-state "INBOX"))))))
(file "~/org/capture-templates/weekly.org"))))
#+end_src
** Babel
#+begin_src emacs-lisp :tangle org-config-config.el
@@ -778,7 +712,6 @@ SCHEDULED: %^t
Note that this does not go into org-config-config.el. This is on purpose
#+begin_src emacs-lisp
(use-package org
:ensure nil
:after frame-mode
:config
(progn
@@ -792,7 +725,7 @@ Note that this does not go into org-config-config.el. This is on purpose
** Disable yasnippet in org-mode
#+BEGIN_SRC emacs-lisp
(use-package org
:ensure nil
:straight nil
:config
(progn
(defun imalison:disable-yas ()
@@ -803,7 +736,6 @@ Note that this does not go into org-config-config.el. This is on purpose
This was taken from [[http://emacs.stackexchange.com/questions/3374/set-the-background-of-org-exported-code-blocks-according-to-theme][here]].
#+BEGIN_SRC emacs-lisp
(use-package org
:ensure nil
:config
(progn
(defun imalison:org-inline-css-hook (exporter)
@@ -851,7 +783,7 @@ This function replaces the default naming scheme with a call to
#+BEGIN_SRC emacs-lisp
(use-package ox
:defer t
:ensure nil
:straight nil
:config
(defun org-export-get-reference (datum info)
"Return a unique reference for DATUM, as a string.
@@ -879,7 +811,7 @@ alphanumeric characters only."
#+BEGIN_SRC emacs-lisp
(use-package ox-html
:commands (org-html-export-as-html org-html-export-as-html)
:ensure nil
:straight nil
:preface
(progn
(defvar imalison:link-svg-html
@@ -911,7 +843,7 @@ alphanumeric characters only."
#+BEGIN_SRC emacs-lisp
(use-package ox-html
:defer t
:ensure nil
:straight nil
:config
(setq org-html-inline-image-rules
'(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'")
@@ -922,7 +854,7 @@ alphanumeric characters only."
** Use org-tempo to allow inserting templates using e.g. <s
#+begin_src emacs-lisp
(use-package org-tempo
:ensure nil
:straight nil
:after org)
#+end_src
* Packages
@@ -1020,6 +952,8 @@ alphanumeric characters only."
:config
(progn
(when (version<= "29.0" emacs-version)
(use-package emacsql-sqlite-builtin
:demand t)
(setq org-roam-database-connector 'sqlite-builtin))
(org-roam-db-autosync-mode +1)
@@ -1041,22 +975,22 @@ alphanumeric characters only."
((get-buffer org-roam-buffer) 'exists)
(t 'none)))
;; org-roam-buffer-visibility-fn was removed in newer org-roam versions
(when (and imalison:use-frame-mode (boundp 'org-roam-buffer-visibility-fn))
(require 'frame-mode)
(emit-variable-set-mode
imalison:org-roam-set-frame-visibility-mode
org-roam-buffer-visibility-fn 'imalison:org-roam-frame-based-buffer-visibility-fn)
(emit-make-mode-dependent imalison:org-roam-set-frame-visibility-mode frame-mode)))
(use-package frame-mode
:if imalison:use-frame-mode
:demand t
:config
(progn
(emit-variable-set-mode
imalison:org-roam-set-frame-visibility-mode
org-roam-buffer-visibility-fn 'imalison:org-roam-frame-based-buffer-visibility-fn)
(emit-make-mode-dependent imalison:org-roam-set-frame-visibility-mode frame-mode))))
:custom
(org-roam-directory (file-truename "~/org/roam/")))
#+end_src
***** ui
#+begin_src emacs-lisp
(use-package simple-httpd
:ensure (:host github :repo "skeeto/emacs-web-server"
:local-repo "simple-httpd"
:files ("simple-httpd.el")))
(use-package emacs-http-server
:demand t)
(use-package org-roam-ui
:after org-roam
@@ -1121,7 +1055,7 @@ alphanumeric characters only."
:config
(progn
(require 'org-fc-hydra))
:ensure (:host github :repo "l3kn/org-fc"
:straight (org-fc :type git :host github :repo "l3kn/org-fc"
:files ("*.el" "awk" "demo.org")))
#+end_src
** org-ql
@@ -1134,10 +1068,11 @@ alphanumeric characters only."
#+begin_src emacs-lisp
(use-package org-window-habit
:demand t
:ensure
(:repo "colonelpanic8/org-window-habit"
:straight
(org-window-habit
:repo "colonelpanic8/org-window-habit"
:host github
:files (:defaults "*.el"))
:files ("org-window-habit.el"))
:custom
((org-window-habit-property-prefix nil)
(org-window-habit-repeat-to-scheduled t)

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python
from __future__ import print_function
import appdirs
import argparse
import os
import struct
clipit_history_file = os.path.join(
appdirs.user_data_dir(), "clipit/history",
)
def get_clipit_history(filename):
with open(filename, 'rb') as f:
f.read(68)
size, _ = struct.unpack('2i', f.read(8))
while (size > 0):
item = f.read(size)
if item:
yield item.decode('utf-8')
_, _, _, size, _ = struct.unpack('5i', f.read(20))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Lookup clipit history')
parser.add_argument(
'--separator', '-s',
help='the separator to use when outputting history',
type=str,
default='\n',
)
parser.add_argument(
'--begin-index', '-b',
type=int,
default=0
)
parser.add_argument(
'--end-index', '-e',
type=int,
default=None
)
parser.add_argument(
'--index', '-i',
type=int,
default=None
)
parser.add_argument(
'--separator-replacement', '-r',
type=str,
default=None
)
args = parser.parse_args()
if not args.separator_replacement:
args.separator_replacement = args.separator
history = list(get_clipit_history(clipit_history_file))
if args.index is not None:
text = history[args.index]
else:
selected = history[args.begin_index:args.end_index]
text = args.separator.join([s.replace(args.separator, args.separator_replacement)
for s in selected])
print(text, end='')

View File

@@ -1,2 +0,0 @@
#!/usr/bin/env bash
rofi -modi "clipboard:greenclip print" -show clipboard

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
SELECTED_INDEX="$(clipit_history.py -r '(newline)' | rofi -dmenu -format i)"
if [ "$SELECTED_INDEX" -eq "$SELECTED_INDEX" ] 2>/dev/null; then
xdotool type "$(clipit_history.py -e 5 -i $SELECTED_INDEX)"
fi
xdotool type

View File

@@ -1,40 +1,13 @@
#!/usr/bin/env zsh
set -euo pipefail
otherinputs () {
get_sink_input_info.hs | jq 'select(.application_process_id != "'"$1"'")'
}
get_active_pid () {
if [[ "${XDG_SESSION_TYPE:-}" == "wayland" ]] && command -v hyprctl >/dev/null 2>&1; then
hyprctl activewindow -j | jq -r '.pid'
else
xprop _NET_WM_PID -id "$(xdotool getactivewindow)" | grep -Eo '[0-9]*'
fi
}
get_sink_info_by_pid () {
local pid="$1"
if command -v pashowinputbypid >/dev/null 2>&1; then
pashowinputbypid "$pid"
else
pactl -f json list sink-inputs | jq -c --arg pid "$pid" '
.[] | select(.properties."application.process.id" == ($pid|tonumber)) |
{ sink_input_id: .index, Mute: (if .mute then "yes" else "no" end) }
' | head -1
fi
}
thePID="$(get_active_pid)"
sinkInfo="$(get_sink_info_by_pid "$thePID")"
if [[ -z "$sinkInfo" ]]; then
exit 0
fi
sinkID="$(echo "$sinkInfo" | jq -r .sink_input_id)"
muted="$(echo "$sinkInfo" | jq -r .Mute)"
thePID="$(xprop _NET_WM_PID -id $(xdotool getactivewindow) | grep -Eo '[0-9]*')"
sinkInfo="$(pashowinputbypid $thePID)"
sinkID="$(echo $sinkInfo | jq -r .sink_input_id)"
muted="$(echo $sinkInfo | jq -r .Mute)"
if [[ $muted == *"no"* ]]; then
newState="1"
else
@@ -43,7 +16,7 @@ fi
echo "$sinkID"
if [[ "${1:-}" == *"only"* ]]; then
if [[ $1 == *"only"* ]]; then
pactl set-sink-input-mute "$sinkID" 0
otherinputs "$thePID" | jq -r .sink_input_id | xargs -I theid sh -c 'pactl set-sink-input-mute theid 1'
else

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env sh
function codex_tmux {
base=$(basename "$PWD")
name="$base"
if tmux has-session -t "$name" 2>/dev/null; then
i=2
while tmux has-session -t "${name}-${i}" 2>/dev/null; do
i=$((i+1))
done
name="${name}-${i}"
fi
tmux new-session -s "$name" -c "$PWD" codex --dangerously-bypass-approvals-and-sandbox "$@"
}
codex_tmux "$@"

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env sh
function passgen {
if [ -z "$1" ]; then
echo "Usage: passgen <pass-entry-name>" >&2
return 1
fi
local base_pass upper symbol password
base_pass="$(xkcdpass -n 3 | tr -d ' ')"
upper="$(echo {A..Z} | tr ' ' '\n' | shuf -n1)"
symbol="$(echo '!@#$%^&*' | fold -w1 | shuf -n1)"
password="${base_pass}${upper}${symbol}"
echo "$password" | pass insert -e "$1"
}
passgen

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env sh
function tn {
if [ -z "$TMUX" ]; then
echo "Not in a tmux session"
return 1
fi
base=$(basename "$PWD")
current=$(tmux display-message -p '#{session_name}')
# Don't rename if already named correctly
if [ "$current" = "$base" ]; then
echo "Session already named '$base'"
return 0
fi
if tmux has-session -t "$base" 2>/dev/null; then
i=2
while tmux has-session -t "${base}-${i}" 2>/dev/null; do
i=$((i+1))
done
tmux rename-session "${base}-${i}"
echo "Renamed session to '${base}-${i}'"
else
tmux rename-session "$base"
echo "Renamed session to '$base'"
fi
}
tn "$@"

View File

@@ -1,3 +1,5 @@
# Create a new Codex session from the current pane path and switch to it.
# Prefix + C starts a new session without prompting for a name.
bind-key C new-session -c '#{pane_current_path}' 'codex --dangerously-bypass-approvals-and-sandbox'
# Automatically rename new sessions to the basename of the current directory
set-hook -g session-created 'run-shell "tmux rename-session -t #{session_name} $(basename #{pane_current_path})"'
# Also rename when attaching to a session (optional)
set-hook -g client-session-changed 'run-shell "tmux rename-session -t #{session_name} $(basename #{pane_current_path})"'

View File

@@ -1,25 +1,20 @@
#!/usr/bin/env bash
# Local compilation script for generating HTML from README.org
# Note: For CI, this is now handled by GitHub Actions (.github/workflows/gh-pages.yml)
set -e
export PATH="$HOME/.cask/bin:$HOME/.evm/bin:$PATH"
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Use system emacs or EMACS environment variable
EMACS="${EMACS:-emacs}"
TARGET=$(readlink -f "$THIS_DIR/../dotfiles/emacs.d/README.org")
cd "$THIS_DIR"
git clone https://github.com/rejeep/evm.git "$HOME/.evm"
evm config path /tmp
evm install emacs-25.1-travis --use --skip
export EMACS="$(evm bin)"
# Install cask dependencies if needed
if [ ! -d ".cask" ]; then
cask install
fi
git clone https://github.com/cask/cask
export PATH=$(pwd)/cask/bin:$PATH
# Generate HTML
cask install
cask exec "$EMACS" --script generate-html.el
# Move the generated file
mv "$THIS_DIR/../dotfiles/emacs.d/README.html" .
echo "Generated README.html in $THIS_DIR"

View File

@@ -1,11 +1,68 @@
#!/usr/bin/env bash
# DEPRECATED: This script was used for Travis CI deployments.
# Deployment is now handled by GitHub Actions (.github/workflows/gh-pages.yml)
#
# This script is kept for reference only.
# See: https://github.com/IvanMalison/dotfiles/blob/master/.github/workflows/gh-pages.yml
# This approach was adapted from https://gist.github.com/domenic/ec8b0fc8ab45f39403dd
echo "ERROR: This script is deprecated."
echo "Deployment is now handled by GitHub Actions."
echo "See: .github/workflows/gh-pages.yml"
exit 1
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $THIS_DIR
git config --global user.name "$COMMIT_AUTHOR_NAME"
git config --global user.email "$COMMIT_AUTHOR_EMAIL"
set -e # Exit with nonzero exit code if anything fails
SOURCE_BRANCH="master"
TARGET_BRANCH="gh-pages"
function doCompile {
./compile.sh
}
# Pull requests and commits to other branches shouldn't try to deploy, just build to verify
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
echo "Skipping deploy; just doing a build."
doCompile
exit 0
fi
# Save some useful information
REPO=`git config remote.origin.url`
SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
SHA=`git rev-parse --verify HEAD`
# Run our compile script
doCompile
# Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy_key.enc -out deploy_key -d
chmod 600 deploy_key
eval `ssh-agent -s`
ssh-add deploy_key
# Clone the existing gh-pages for this repo into out/
# Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
git clone $REPO out
cd out
git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
# Clean out existing contents
git ls-files | xargs rm -rf
mv ../README.html ./index.html
# Commit the "changes", i.e. the new version.
# The delta will show diffs between new and old versions.
git add --all .
git commit -m "Deploy to GitHub Pages: ${SHA}"
git fetch origin master
if [ "$(git rev-parse origin/master)" == "$SHA" ]; then
git push "$SSH_REPO" "$TARGET_BRANCH"
else
echo "The commit this build was started for is not the one on master. Doing nothing."
fi

BIN
gen-gh-pages/deploy_key.enc Normal file

Binary file not shown.

View File

@@ -19,9 +19,12 @@
(require 's)
(org-babel-tangle-file readme-src)
(require 'cl-lib)
(load-file (concat emacs-dir "org-config-bootstrap.el"))
(org-babel-tangle-file (concat emacs-dir "org-config.org"))
;; This makes it so that any dependencies specified with :straight, will
;; actually just be installed with the default melpa use-package ensure logic.
(defalias 'use-package-handler/:straight
#'use-package-handler/:ensure)
(add-to-list 'use-package-keywords :straight)
(load-file (concat emacs-dir "org-config.el"))
(defun export-target (target)

114
nix-darwin/flake.lock generated
View File

@@ -8,7 +8,7 @@
"railbird-secrets",
"nixpkgs"
],
"systems": "systems_3"
"systems": "systems"
},
"locked": {
"lastModified": 1707830867,
@@ -41,48 +41,6 @@
"type": "github"
}
},
"claude-code-nix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1770168651,
"narHash": "sha256-SxzTEu49iaAA/nAT28Rsr4BmjC3eCkiaM4/ZYBVhhNQ=",
"owner": "sadjow",
"repo": "claude-code-nix",
"rev": "f256f48c037a6e54afa332795328f753f2fafbaf",
"type": "github"
},
"original": {
"owner": "sadjow",
"repo": "claude-code-nix",
"type": "github"
}
},
"codex-cli-nix": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1770232831,
"narHash": "sha256-C5e2wjd//pLJA1LqSYc/y9aZkM8wmZo/BAuzhZDuyFE=",
"owner": "sadjow",
"repo": "codex-cli-nix",
"rev": "64805eb1d1afffcbbcef0ffc053295f0065cd51d",
"type": "github"
},
"original": {
"owner": "sadjow",
"repo": "codex-cli-nix",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
@@ -107,45 +65,9 @@
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1709126324,
"narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
@@ -307,7 +229,7 @@
"railbird-secrets": {
"inputs": {
"agenix": "agenix",
"flake-utils": "flake-utils_3",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs_2"
},
"locked": {
@@ -326,8 +248,6 @@
},
"root": {
"inputs": {
"claude-code-nix": "claude-code-nix",
"codex-cli-nix": "codex-cli-nix",
"home-manager": "home-manager",
"homebrew-cask": "homebrew-cask",
"homebrew-core": "homebrew-core",
@@ -366,36 +286,6 @@
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

View File

@@ -21,16 +21,6 @@
};
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
codex-cli-nix = {
url = "github:sadjow/codex-cli-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
claude-code-nix = {
url = "github:sadjow/claude-code-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{ self, nix-darwin, nixpkgs, home-manager, ... }:
@@ -122,14 +112,7 @@
};
};
nixpkgs.overlays = [
(import ../nixos/overlay.nix)
# Use codex and claude-code from dedicated flakes with cachix
(final: prev: {
codex = inputs.codex-cli-nix.packages.${prev.stdenv.hostPlatform.system}.default;
claude-code = inputs.claude-code-nix.packages.${prev.stdenv.hostPlatform.system}.default;
})
];
nixpkgs.overlays = [(import ../nixos/overlay.nix)];
environment.systemPackages = with pkgs; [
#python-with-my-packages
emacs
@@ -143,8 +126,7 @@
nodejs
ripgrep
slack
claude-code
codex
claude-code
typescript
vim
yarn
@@ -159,18 +141,7 @@
programs.direnv.enable = true;
# Necessary for using flakes on this system.
nix.settings = {
experimental-features = "nix-command flakes";
substituters = [
"https://cache.nixos.org"
"https://codex-cli.cachix.org"
"https://claude-code.cachix.org"
];
trusted-public-keys = [
"codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing="
"claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk="
];
};
nix.settings.experimental-features = "nix-command flakes";
# Set Git commit hash for darwin-version.

View File

@@ -1,80 +0,0 @@
---
name: bump-overlay-versions
description: Use when user asks to bump, update, or upgrade claude-code or codex versions in overlay.nix, or when checking if newer versions are available
---
# Bump Overlay Versions
## Overview
Updates claude-code and/or codex to latest versions in `~/dotfiles/nixos/overlay.nix`. Nix requires correct hashes which must be discovered through failed builds.
## Quick Reference
| Package | Check Latest | Hash Fields |
|---------|--------------|-------------|
| claude-code | `npm view @anthropic-ai/claude-code version` | `hash`, `npmDepsHash` (keep empty) |
| codex | `curl -s "https://api.github.com/repos/openai/codex/releases/latest" \| jq -r '.tag_name'` | `hash`, `cargoHash` |
## Workflow
### 1. Check Current vs Latest Versions
```bash
# Current versions are in overlay.nix claudeCodeVersion and codexVersion blocks
# Check latest:
npm view @anthropic-ai/claude-code version
curl -s "https://api.github.com/repos/openai/codex/releases/latest" | jq -r '.tag_name'
# codex tag format: rust-v0.92.0 -> version is 0.92.0
```
### 2. Update Version and Clear Hashes
In `~/dotfiles/nixos/overlay.nix`:
**For claude-code:**
```nix
claudeCodeVersion = {
version = "X.Y.Z"; # Update to new version
hash = ""; # Clear - will get from build error
npmDepsHash = ""; # Keep empty (no npm deps)
};
```
**For codex:**
```nix
codexVersion = {
version = "X.Y.Z"; # Update to new version (without rust-v prefix)
hash = ""; # Clear - will get from build error
cargoHash = ""; # Clear - will get from build error
};
```
### 3. Build to Get Hashes
```bash
just switch
```
The build will fail with hash mismatch errors showing the correct hash. Copy the `got:` hash value.
**For codex:** You'll need to run twice - once for `hash` (source), once for `cargoHash` (cargo deps).
### 4. Update with Correct Hashes
Replace empty strings with the hashes from build errors, then run `just switch` again.
## Enable/Disable Overrides
The overlay uses boolean flags - set to `false` to use nixpkgs versions instead:
```nix
enableCodexOverride = true; # Set false to use nixpkgs codex
enableClaudeCodeOverride = true; # Set false to use nixpkgs claude-code
```
**Never delete the override code** - just toggle the flags.
## File Location
`~/dotfiles/nixos/overlay.nix`

View File

@@ -3,7 +3,10 @@
options = {
};
config = {
environment.systemPackages = with pkgs; [
android-udev-rules
];
nixpkgs.config.android_sdk.accept_license = true;
environment.systemPackages = [ pkgs.android-tools ];
programs.adb.enable = true;
};
}

View File

@@ -1,4 +1,4 @@
{ config, pkgs, makeEnable, realUsers, ... }:
{ config, pkgs, forEachUser, makeEnable, realUsers, ... }:
makeEnable config "myModules.base" true {
nixpkgs.config.permittedInsecurePackages = [
"electron-12.2.3"
@@ -65,19 +65,13 @@ makeEnable config "myModules.base" true {
defaultLocale = "en_US.UTF-8";
};
# Update timezone automatically
# The tzupdate.timer handles triggering with OnStartupSec=30s delay.
# We disable the service's direct WantedBy since network-online.target
# is reached before network is actually online (because we disable
# NetworkManager-wait-online.service to avoid boot hangs).
# # Update timezone automatically
services.tzupdate.enable = true;
systemd.services.tzupdate.wantedBy = pkgs.lib.mkForce [];
# TODO: Add a comment explaining what this does.
services.locate.enable = true;
virtualisation.docker.enable = true;
services.orca.enable = false;
virtualisation.podman = {
enable = true;
@@ -88,10 +82,13 @@ makeEnable config "myModules.base" true {
hardware.keyboard.zsa.enable = true;
services.logind.extraConfig = "RuntimeDirectorySize=5G";
# For supporting gnome stuff
services.dbus.packages = [ pkgs.gcr ];
programs.dconf.enable = true;
home-manager.users = forEachUser (import ./home-manager.nix);
nix.settings.trusted-users = realUsers ++ ["gitea-runner"];
}

View File

@@ -97,7 +97,9 @@
specialArgs = rec {
inherit inputs machineNames;
makeEnable = (import ../make-enable.nix) nixpkgs.lib;
mapValueToKeys = keys: value: builtins.listToAttrs (map (name: { inherit name value; }) keys);
realUsers = [ "root" "imalison" "kat" "dean" "alex" "ben"];
forEachUser = mapValueToKeys realUsers;
} // specialArgs // (import ../keys.nix);
});
in

View File

@@ -7,16 +7,15 @@ makeEnable config "myModules.code" true {
environment.systemPackages = with pkgs; [
# LLM Tools
antigravity
claude-code
codex
gemini-cli
opencode
# MCP
github-mcp-server
gitea-mcp-server
mcp-nixos
playwright-mcp
mcp-language-server
# C
clang
@@ -48,7 +47,6 @@ makeEnable config "myModules.code" true {
# Rust
rustup
cargo-sweep
# Clojure
boot
@@ -78,7 +76,7 @@ makeEnable config "myModules.code" true {
nixd
nil
alejandra
] ++ (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then with pkgs; [
] ++ (if pkgs.system == "x86_64-linux" then with pkgs; [
# purescript
purescript
# Broken

View File

@@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, forEachUser, ... }:
{
imports = [
./android.nix
@@ -42,7 +42,6 @@
./wsl.nix
./wyoming.nix
./xmonad.nix
./org-agenda-api-host.nix
];
options = {

View File

@@ -1,10 +1,7 @@
{ inputs, config, pkgs, makeEnable, ... }:
makeEnable config "myModules.desktop" true {
services.greenclip.enable = true;
imports = [
./fonts.nix
./hyprland.nix
./keyd.nix
];
services.xserver = {
@@ -24,6 +21,8 @@ makeEnable config "myModules.desktop" true {
};
};
programs.hyprland.enable = true;
services.autorandr = {
enable = true;
};
@@ -41,14 +40,13 @@ makeEnable config "myModules.desktop" true {
# Appearance
adwaita-icon-theme
hicolor-icon-theme
# libsForQt5.breeze-gtk
libsForQt5.breeze-gtk
# materia-theme
numix-icon-theme-circle
papirus-icon-theme
# XOrg
autorandr
keyd
wmctrl
xclip
xdotool
@@ -59,15 +57,16 @@ makeEnable config "myModules.desktop" true {
# Desktop
alacritty
ghostty
blueman
# clipit
d-spy
kdePackages.dolphin
# inputs.ghostty.packages."${system}".default
feh
firefox
cheese
gpaste
kdePackages.kleopatra
libnotify
libreoffice
@@ -75,7 +74,7 @@ makeEnable config "myModules.desktop" true {
lxqt.lxqt-powermanagement
networkmanagerapplet
kdePackages.okular
pinentry-gnome3
pinentry
# mission-center
quassel
remmina
@@ -89,7 +88,7 @@ makeEnable config "myModules.desktop" true {
# TODO: reenable
# transmission_3-gtk
vlc
thunar
xfce.thunar
# Audio
picard
@@ -104,13 +103,13 @@ makeEnable config "myModules.desktop" true {
# Visualization
graphviz
nodePackages.mermaid-cli
] ++ (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then with pkgs; [
] ++ (if pkgs.system == "x86_64-linux" then with pkgs; [
google-chrome
pommed_light
slack
spicetify-cli
spotify
tor-browser
tor-browser-bundle-bin
vscode
zulip
] else []);

View File

@@ -1,4 +1,4 @@
{ pkgs, config, makeEnable, ... }:
{ pkgs, config, makeEnable, forEachUser, ... }:
makeEnable config "myModules.electron" false {
environment.systemPackages = with pkgs; [
element-desktop
@@ -8,23 +8,21 @@ makeEnable config "myModules.electron" false {
# keybase-gui
zoom-us
];
home-manager.sharedModules = [
(if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then {
# systemd.user.services.bitwarden = {
# Unit = {
# Description = "Bitwarden";
# After = [ "graphical-session-pre.target" "tray.target" ];
# PartOf = [ "graphical-session.target" ];
# };
home-manager.users = forEachUser (if pkgs.system == "x86_64-linux" then {
# systemd.user.services.bitwarden = {
# Unit = {
# Description = "Bitwarden";
# After = [ "graphical-session-pre.target" "tray.target" ];
# PartOf = [ "graphical-session.target" ];
# };
# Install = { WantedBy = [ "graphical-session.target" ]; };
# Install = { WantedBy = [ "graphical-session.target" ]; };
# Service = {
# ExecStart = "${pkgs.bitwarden}/bin/bitwarden";
# Restart = "always";
# RestartSec = 3;
# };
# };
} else {})
];
# Service = {
# ExecStart = "${pkgs.bitwarden}/bin/bitwarden";
# Restart = "always";
# RestartSec = 3;
# };
# };
} else {});
}

View File

@@ -26,6 +26,7 @@
git-lfs
git-sync
gitFull
glxinfo
gnumake
gparted
home-manager
@@ -38,7 +39,6 @@
lshw
lsof
magic-wormhole-rs
mesa-demos
ncdu
neofetch
neovim

View File

@@ -1,5 +1,7 @@
{ config, pkgs, makeEnable, ... }:
makeEnable config "myModules.extra" false {
programs.hyprland.enable = true;
environment.systemPackages = with pkgs; [
android-studio
gradle

1842
nixos/flake.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
inputs.systems.follows = "systems";
};
systems = {url = "github:nix-systems/default";};
systems = { url = "github:nix-systems/default"; };
git-ignore-nix = {
url = "github:hercules-ci/gitignore.nix";
@@ -21,38 +21,15 @@
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-hardware = {url = "github:colonelpanic8/nixos-hardware/my-master";};
nixos-hardware = { url = "github:colonelpanic8/nixos-hardware/my-master"; };
nixos-wsl = {url = "github:nix-community/NixOS-WSL";};
nixos-wsl = { url = "github:nix-community/NixOS-WSL"; };
agenix = {url = "github:ryantm/agenix";};
org-agenda-api = {
url = "github:colonelpanic8/org-agenda-api";
inputs.nixpkgs.follows = "nixpkgs";
};
# Hyprland and plugins from official flakes for proper plugin compatibility
hyprland = {
url = "git+https://github.com/hyprwm/Hyprland?submodules=1&ref=refs/tags/v0.53.0";
};
hy3 = {
url = "github:outfoxxed/hy3?ref=hl0.53.0";
inputs.hyprland.follows = "hyprland";
};
hyprland-plugins = {
url = "github:hyprwm/hyprland-plugins?ref=v0.53.0";
inputs.hyprland.follows = "hyprland";
};
agenix = { url = "github:ryantm/agenix"; };
railbird-secrets = {
url = "git+ssh://gitea@dev.railbird.ai:1123/railbird/secrets-flake.git";
};
# railbird-secrets = {
# url = "git+ssh://gitea@dev.railbird.ai:1123/railbird/secrets-flake.git";
# };
xmonad = {
url = "github:xmonad/xmonad";
@@ -127,102 +104,16 @@
vscode-server.url = "github:nix-community/nixos-vscode-server";
nixified-ai = {url = "github:nixified-ai/flake";};
nixified-ai = { url = "github:nixified-ai/flake"; };
nixtheplanet.url = "github:matthewcroughan/nixtheplanet";
codex-cli-nix = {
url = "github:sadjow/codex-cli-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
claude-code-nix = {
url = "github:sadjow/claude-code-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs @ {
self,
nixpkgs,
nixos-hardware,
home-manager,
taffybar,
xmonad,
nixtheplanet,
xmonad-contrib,
notifications-tray-icon,
nix,
agenix,
imalison-taffybar,
hyprland,
hy3,
hyprland-plugins,
org-agenda-api,
flake-utils,
...
}: let
# Nixpkgs PR patches - just specify PR number and hash
nixpkgsPRPatches = [
{
pr = 434160; # git-sync-rs package
hash = "sha256-0j0IcyHd7rE+MXc0SHu8UixW7Jbtzu1NnzSjEVeZmTA=";
}
# claude-code
# {
# pr = 464698;
# hash = "sha256-Pe9G6b/rI0874mM7FIOSEKiaubk95NcFhTQ7paAeLTU=";
# }
# {
# pr = 464816;
# hash = "sha256-bKEoRy4dzP5TyRBjYskwEzr7tj8/ez/Y1XHiQgu5q5I=";
# }
];
# Custom patches that don't fit the PR template
nixpkgsCustomPatches = [
];
# Home-manager PR patches - just specify PR number and hash
homeManagerPRPatches = [
# Example:
# {
# pr = 1234;
# hash = "sha256-...";
# }
];
# Custom home-manager patches that don't fit the PR template
homeManagerCustomPatches = [
{
url = "https://github.com/colonelpanic8/home-manager/commit/92f4b7aa5254f8bcddc9ef86e04ea5314410d10b.patch";
hash = "sha256-RQl5daVpCqQi05l9QfTEz2PpQxmsv/HYnXrgXbqbwWk=";
}
];
# Convert PR patches to full patch format for nixpkgs
nixpkgsPrPatchesToPatches = prPatches:
map (p: {
url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/${toString p.pr}.patch";
hash = p.hash;
})
prPatches;
# Convert PR patches to full patch format for home-manager
homeManagerPrPatchesToPatches = prPatches:
map (p: {
url = "https://patch-diff.githubusercontent.com/raw/nix-community/home-manager/pull/${toString p.pr}.patch";
hash = p.hash;
})
prPatches;
# Combine all nixpkgs patches
allNixpkgsPatches = (nixpkgsPrPatchesToPatches nixpkgsPRPatches) ++ nixpkgsCustomPatches;
# Combine all home-manager patches
allHomeManagerPatches = (homeManagerPrPatchesToPatches homeManagerPRPatches) ++ homeManagerCustomPatches;
outputs = inputs@{
self, nixpkgs, nixos-hardware, home-manager, taffybar, xmonad, nixtheplanet,
xmonad-contrib, notifications-tray-icon, nix, agenix, imalison-taffybar, ...
}:
let
machinesFilepath = ./machines;
machineFilenames = builtins.attrNames (builtins.readDir machinesFilepath);
machineNameFromFilename = filename: builtins.head (builtins.split "\\." filename);
@@ -230,33 +121,13 @@
mkConfigurationParams = filename: {
name = machineNameFromFilename filename;
value = {
baseModules = [
(machinesFilepath + ("/" + filename))
agenix.nixosModules.default
nixtheplanet.nixosModules.macos-ventura
modules = [
(machinesFilepath + ("/" + filename)) agenix.nixosModules.default nixtheplanet.nixosModules.macos-ventura
];
};
};
defaultConfigurationParams =
builtins.listToAttrs (map mkConfigurationParams machineFilenames);
# Build org-agenda-api container for a given system
mkOrgAgendaApiContainerInfo = system: let
pkgs = import nixpkgs { inherit system; };
orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown");
dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty");
dotfilesOrgApi = import ./org-agenda-api.nix {
inherit pkgs system inputs;
};
tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
containerLib = import ../org-agenda-api/container.nix {
inherit pkgs system tangledConfig org-agenda-api orgApiRev dotfilesRev;
};
tag = "colonelpanic-${orgApiRev}-${dotfilesRev}";
in {
imageFile = containerLib.containers.colonelpanic;
imageName = "org-agenda-api:${tag}";
};
customParams = {
biskcomp = {
system = "aarch64-linux";
@@ -264,22 +135,15 @@
air-gapped-pi = {
system = "aarch64-linux";
};
railbird-sf = {
specialArgs = let
containerInfo = mkOrgAgendaApiContainerInfo "x86_64-linux";
in {
orgAgendaApiContainer = containerInfo.imageFile;
orgAgendaApiImageName = containerInfo.imageName;
};
};
};
mkConfig = {
system ? "x86_64-linux",
baseModules ? [],
modules ? [],
specialArgs ? {},
...
}: let
mkConfig =
{ system ? "x86_64-linux"
, baseModules ? []
, modules ? []
, specialArgs ? {}
, ...
}:
let
# Bootstrap nixpkgs for this specific system
bootstrapPkgs = import nixpkgs {
inherit system;
@@ -290,68 +154,47 @@
patchedSource = bootstrapPkgs.applyPatches {
name = "nixpkgs-patched";
src = nixpkgs;
patches = map bootstrapPkgs.fetchpatch allNixpkgsPatches;
prePatch = ''
mkdir -p pkgs/by-name/an/antigravity
'';
patches = [
# Rumno service PR
(bootstrapPkgs.fetchpatch {
url = "https://github.com/NixOS/nixpkgs/pull/433540.patch";
hash = "sha256-G4eJaX351/HMB0z4QNfgob+bVuqCcTEMGE7IPNcIGbw=";
})
# git-sync-rs package
(bootstrapPkgs.fetchpatch {
url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/434160.patch";
hash = "sha256-1xm75lWEKWbX0qsbeXWX3lRRZIFO3/sdrZZYJxKGD2o=";
})
(bootstrapPkgs.fetchpatch {
url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/436061.patch";
hash = "sha256-HZquaNBB+w5Hm5kdzvaGg7QAOgAf/EPBO7o7pKkIrMY=";
})
];
};
# Get eval-config from patched source
evalConfig = import "${patchedSource}/nixos/lib/eval-config.nix";
# Apply patches to home-manager source (only if there are patches)
patchedHomeManagerSource =
if allHomeManagerPatches == []
then home-manager
else
bootstrapPkgs.applyPatches {
name = "home-manager-patched";
src = home-manager;
patches = map bootstrapPkgs.fetchpatch allHomeManagerPatches;
};
# Import the patched home-manager flake
patchedHomeManager =
if allHomeManagerPatches == []
then home-manager
else import "${patchedHomeManagerSource}/flake.nix";
# Get the NixOS module from the patched source
patchedHomeManagerModule =
if allHomeManagerPatches == []
then home-manager.nixosModules.home-manager
else import "${patchedHomeManagerSource}/nixos";
# Create a modified inputs with patched home-manager
patchedInputs = inputs // {
home-manager = inputs.home-manager // {
nixosModules = inputs.home-manager.nixosModules // {
home-manager = patchedHomeManagerModule;
};
# Also provide the patched source path for any direct imports
outPath = patchedHomeManagerSource.outPath or "${patchedHomeManagerSource}";
};
};
in
evalConfig {
inherit system;
modules = baseModules ++ modules;
specialArgs =
rec {
inputs = patchedInputs;
inherit machineNames;
makeEnable = (import ./make-enable.nix) nixpkgs.lib;
keys = import ./keys.nix;
usersInfo = (import ./users.nix) {
pkgs = {zsh = "zsh";};
inherit keys system;
inputs = patchedInputs;
};
realUsers = (
builtins.attrNames
(nixpkgs.lib.filterAttrs
(_: value: (builtins.elem "isNormalUser" (builtins.attrNames value)) && value.isNormalUser)
usersInfo.users.users)
);
}
// specialArgs;
};
in {
evalConfig {
inherit system;
modules = baseModules ++ modules;
specialArgs = rec {
inherit inputs machineNames;
makeEnable = (import ./make-enable.nix) nixpkgs.lib;
keys = (import ./keys.nix);
usersInfo = (import ./users.nix) {
pkgs = { zsh = "zsh"; };
inherit keys inputs system;
};
realUsers = (builtins.attrNames
(nixpkgs.lib.filterAttrs
(_: value: (builtins.elem "isNormalUser" (builtins.attrNames value)) && value.isNormalUser) usersInfo.users.users)
);
mapAllKeysToValue = keys: value: builtins.listToAttrs (map (name: { inherit name value; }) keys);
forEachUser = mapAllKeysToValue realUsers;
} // specialArgs;
};
in
{
nixConfig = {
substituters = [
"https://cache.nixos.org/"
@@ -361,79 +204,17 @@
];
extra-substituters = [
"http://192.168.1.26:5050"
"https://cache.flox.dev"
"https://org-agenda-api.cachix.org"
"https://codex-cli.cachix.org"
"https://claude-code.cachix.org"
];
extra-trusted-public-keys = [
"1896Folsom.duckdns.org:U2FTjvP95qwAJo0oGpvmUChJCgi5zQoG1YisoI08Qoo="
"flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs="
"org-agenda-api.cachix.org-1:liKFemKkOLV/rJt2txDNcpDjRsqLuBneBjkSw/UVXKA="
"codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing="
"claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk="
];
};
nixosConfigurations =
builtins.mapAttrs (
machineName: params: let
machineParams =
if builtins.hasAttr machineName customParams
then (builtins.getAttr machineName customParams)
else {};
in
mkConfig (params // machineParams)
)
defaultConfigurationParams;
} // flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
# Get short revs for tagging
orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown");
dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty");
# Get tangled config files from org-agenda-api.nix
dotfilesOrgApi = import ./org-agenda-api.nix {
inherit pkgs system;
inherit inputs;
};
tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
# Import container build logic
containerLib = import ../org-agenda-api/container.nix {
inherit pkgs system tangledConfig org-agenda-api orgApiRev dotfilesRev;
};
in {
packages = {
colonelpanic-org-agenda-api = containerLib.containers.colonelpanic;
kat-org-agenda-api = containerLib.containers.kat;
};
# Dev shell for org-agenda-api deployment
devShells.org-agenda-api = pkgs.mkShell {
buildInputs = [
pkgs.flyctl
agenix.packages.${system}.default
pkgs.age
pkgs.ssh-to-age
pkgs.git
pkgs.jq
pkgs.just
pkgs.curl
];
shellHook = ''
echo ""
echo "org-agenda-api deployment shell"
echo ""
echo "Commands:"
echo " just --list - Show available API commands"
echo " ./deploy.sh <instance> - Deploy to Fly.io (colonelpanic or kat)"
echo " flyctl - Fly.io CLI"
echo " agenix -e <file> - Edit encrypted secrets"
echo ""
'';
};
}
);
nixosConfigurations = builtins.mapAttrs (machineName: params:
let machineParams =
if builtins.hasAttr machineName customParams
then (builtins.getAttr machineName customParams)
else {};
in mkConfig (params // machineParams)
) defaultConfigurationParams;
};
}

View File

@@ -15,7 +15,7 @@ makeEnable config "myModules.fonts" true {
fira-mono
font-awesome
noto-fonts-color-emoji
noto-fonts-emoji
roboto
source-code-pro
source-sans-pro

View File

@@ -14,8 +14,6 @@ makeEnable config "myModules.gitea-runner" false {
};
container = {
workdir_parent = "${gitea-runner-directory}/workspace";
# Increase shared memory for containers (default 64MB is too small for Metro/Gradle)
options = "--shm-size=2g";
};
host = {
workdir_parent = "${gitea-runner-directory}/action-cache-dir";
@@ -42,18 +40,16 @@ makeEnable config "myModules.gitea-runner" false {
url = "https://dev.railbird.ai";
tokenFile = config.age.secrets.gitea-runner-token.path;
labels = [
"nixos-${pkgs.stdenv.hostPlatform.system}:host"
"nixos-${pkgs.system}:host"
"nix:docker://localhost:5921/nix-runner"
];
};
systemd.services.gitea-runner-nix = {
environment = let gitea-runner-directory = "/var/lib/gitea-runner"; in {
systemd.services.gitea-runner-nix.environment =
let gitea-runner-directory = "/var/lib/gitea-runner"; in {
XDG_CONFIG_HOME = gitea-runner-directory;
XDG_CACHE_HOME = "${gitea-runner-directory}/.cache";
};
serviceConfig.PrivateTmp = false;
};
users.groups.gitea-runner = {};
users.users.gitea-runner = {
isSystemUser = true;

View File

@@ -1,25 +1,5 @@
{ pkgs, ... }:
{
# Automatic garbage collection of old home-manager generations
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
xdg.configFile."greenclip.toml".text = ''
[greenclip]
history_file = "~/.cache/greenclip.history"
max_history_length = 50
max_selection_size_bytes = 0
trim_space_from_selection = true
use_primary_selection_as_input = false
blacklisted_applications = []
enable_image_support = true
image_cache_directory = "~/.cache/greenclip"
static_history = []
'';
xsession = {
enable = true;
preferStatusNotifierItems = true;
@@ -31,22 +11,7 @@
programs.home-manager.enable = true;
programs.ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = {
"*" = {
forwardAgent = true;
addKeysToAgent = "no";
compression = false;
serverAliveInterval = 0;
serverAliveCountMax = 3;
hashKnownHosts = false;
userKnownHostsFile = "~/.ssh/known_hosts";
controlMaster = "no";
controlPath = "~/.ssh/master-%r@%n:%p";
controlPersist = "no";
};
};
forwardAgent = true;
};
services.gpg-agent = {
@@ -60,6 +25,22 @@
'';
};
systemd.user.services.setxkbmap = {
Unit = {
Description = "Set up keyboard in X";
After = [ "graphical-session-pre.target" ];
PartOf = [ "graphical-session.target" ];
};
Install = { WantedBy = [ "graphical-session.target" ]; };
Service = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "/usr/bin/env load_xkb_map";
};
};
gtk = {
enable = true;
iconTheme = {
@@ -68,7 +49,7 @@
};
font = {
package = pkgs.noto-fonts-color-emoji;
package = pkgs.noto-fonts-emoji;
name = "Noto Sans";
size = 10;
};

View File

@@ -1,58 +0,0 @@
{ config, pkgs, lib, makeEnable, inputs, ... }:
makeEnable config "myModules.hyprland" true {
programs.hyprland = {
enable = true;
# Use Hyprland from the flake for proper plugin compatibility
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
# Let UWSM manage the Hyprland session targets
withUWSM = true;
};
home-manager.sharedModules = [
{
programs.waybar.enable = true;
systemd.user.services.waybar = {
Unit = {
Description = "Waybar";
PartOf = [ "wayland-session@Hyprland.target" ];
After = [ "wayland-session@Hyprland.target" ];
};
Service = {
ExecStartPre = "${pkgs.bash}/bin/bash -lc 'uid=$(id -u); for i in $(seq 1 50); do runtime_dir=\"$XDG_RUNTIME_DIR\"; if [ -z \"$runtime_dir\" ]; then runtime_dir=\"/run/user/$uid\"; fi; if [ -n \"$WAYLAND_DISPLAY\" ] && [ -S \"$runtime_dir/$WAYLAND_DISPLAY\" ]; then exit 0; fi; sleep 0.1; done; exit 1'";
ExecStart = "${pkgs.waybar}/bin/waybar";
Restart = "always";
RestartSec = 1;
};
Install = {
WantedBy = [ "wayland-session@Hyprland.target" ];
};
};
}
];
# Hyprland-specific packages
environment.systemPackages = with pkgs; [
# Hyprland utilities
hyprpaper # Wallpaper
hypridle # Idle daemon
hyprlock # Screen locker
hyprcursor # Cursor themes
wl-clipboard # Clipboard for Wayland
wtype # Wayland input typing
cliphist # Clipboard history
grim # Screenshot utility
slurp # Region selection
swappy # Screenshot annotation
wlsunset # Night light / blue light filter
# hy3 plugin from flake (properly built against matching Hyprland)
inputs.hy3.packages.${pkgs.stdenv.hostPlatform.system}.hy3
# Hyprexpo plugin from hyprland-plugins (workspace overview)
inputs.hyprland-plugins.packages.${pkgs.stdenv.hostPlatform.system}.hyprexpo
# For scripts
jq
];
}

View File

@@ -3,3 +3,12 @@ switch *args:
fix-local-path-issue:
nix flake update imalison-taffybar
expire-home-manager-generations:
#!/usr/bin/env bash
set -euxo pipefail
for user in $(awk -F':' '{ if ($3 >= 1000 && $7 !~ /nologin|false|sync|shutdown|halt/) print $1 }' /etc/passwd); do
echo $user
sudo su - $user -c 'home-manager expire-generations -1days'
done

View File

@@ -1,5 +1,5 @@
{ ... }: {
home-manager.sharedModules = [
{ services.kbfs.enable = true; }
];
{ forEachUser, ... }: {
home-manager.users = forEachUser {
services.kbfs.enable = true;
};
}

View File

@@ -1,39 +0,0 @@
{ config, lib, makeEnable, ... }:
makeEnable config "myModules.keyd" true {
services.keyd = {
enable = true;
# Base remap applied to all keyboards.
keyboards.default = {
# Exclude the Glove80 (MoErgo) by vendor:product ID.
ids = [ "*" "-16c0:27db" ];
settings = {
main = {
# Caps Lock -> Control
capslock = "leftcontrol";
# Swap Left Alt and Left Super
leftalt = "leftmeta";
leftmeta = "leftalt";
# Right Alt -> Hyper chord
rightalt = "layer(hyper)";
};
# Hyper = Ctrl+Alt+Meta while held (matches $hyper = SUPER CTRL ALT)
"hyper:C-A-M" = { };
};
};
# TODO: Add per-keyboard overrides here once device IDs are known.
# Example:
# keyboards.externalKinesis = {
# ids = [ "1ea7:0907" ];
# settings = {
# main = {
# leftalt = "leftmeta";
# leftmeta = "leftalt";
# rightalt = "layer(hyper)";
# };
# "hyper:C-A-M-S" = { };
# };
# };
};
}

View File

@@ -1,4 +1,6 @@
{ makeEnable, config, ... }:
makeEnable config "myModules.laptop" true {
services.logind.settings.Login.HandleLidSwitchExternalPower = "ignore";
services.logind = {
lidSwitchExternalPower = "ignore";
};
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, inputs, ... }:
{ lib, pkgs, inputs, forEachUser, ... }:
{
imports = [
@@ -71,11 +71,9 @@
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
home-manager.sharedModules = [
{
home.stateVersion = "23.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.05";
};
system.stateVersion = "23.05";
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, ... }:
{ lib, pkgs, config, inputs, forEachUser, ... }:
{
imports = [
../configuration.nix
@@ -18,11 +18,9 @@
wsl.defaultUser = "ben";
system.stateVersion = "22.05";
home-manager.sharedModules = [
{
home.stateVersion = "22.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "22.05";
};
users.users.ben = {
extraGroups = [

View File

@@ -1,4 +1,4 @@
{ pkgs, lib, config, ... }:
{ pkgs, lib, forEachUser, config, ... }:
let biskcomp-nginx-hostnames = "192.168.1.44 railbird.ai 1896Folsom.duckdns.org biskcomp.local 0.0.0.0 67.162.131.71";
in
{
@@ -100,12 +100,41 @@ in
database.ignorePostgresqlVersion = true;
};
systemd.services.emacs-org-api = {
description = "Emacs org api";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = ''${pkgs.runtimeShell} -l -c "${lib.getExe' pkgs.emacs "emacs"} --load /home/imalison/.emacs.d/org-api.el --daemon=org-api"'';
RemainAfterExit = true;
Restart = "on-failure";
User = "imalison";
};
};
age.secrets.org-api-passwords = {
file = ../secrets/org-api-passwords.age;
owner = "nginx";
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedGzipSettings = true;
recommendedTlsSettings = true;
virtualHosts = {
"org-mode.1896Folsom.duckdns.org" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:2025";
basicAuthFile = config.age.secrets.org-api-passwords.path;
extraConfig = ''
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
'';
};
};
"gitlab.railbird.ai" = {
enableACME = true;
forceSSL = true;
@@ -157,9 +186,7 @@ in
networking.hostName = "biskcomp";
system.stateVersion = "23.11";
home-manager.sharedModules = [
{
home.stateVersion = "23.11";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.11";
};
}

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, forEachUser, ... }:
{
imports = [
@@ -53,11 +53,9 @@
networking.hostName = "david-blade";
home-manager.sharedModules = [
{
home.stateVersion = "24.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "24.05";
};
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
system.stateVersion = "24.05";

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, ... }:
{ lib, pkgs, config, inputs, forEachUser, ... }:
{
imports = [
../configuration.nix
@@ -15,9 +15,7 @@
wsl.defaultUser = "dean";
system.stateVersion = "22.05";
home-manager.sharedModules = [
{
home.stateVersion = "22.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "22.05";
};
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, ... }:
{ lib, pkgs, config, inputs, forEachUser, ... }:
{
imports = [
../configuration.nix
@@ -12,9 +12,7 @@
wsl.defaultUser = "kat";
system.stateVersion = "22.05";
home-manager.sharedModules = [
{
home.stateVersion = "22.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "22.05";
};
}

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, forEachUser, ... }:
{
imports = [
@@ -55,9 +55,7 @@
system.stateVersion = "23.05";
home-manager.sharedModules = [
{
home.stateVersion = "23.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.05";
};
}

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, forEachUser, ... }:
{
imports = [
@@ -19,63 +19,6 @@
myModules.fonts.enable = true;
myModules.gitea-runner.enable = true;
myModules.postgres.enable = true;
myModules.gitea.enable = true;
age.secrets.vaultwarden-environment-file = {
file = ../secrets/vaultwarden-environment-file.age;
owner = "vaultwarden";
};
services.vaultwarden = {
enable = true;
backupDir = "/var/backup/vaultwarden";
environmentFile = config.age.secrets.vaultwarden-environment-file.path;
config = {
ROCKET_ADDRESS = "::1";
ROCKET_PORT = 8222;
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedGzipSettings = true;
recommendedTlsSettings = true;
virtualHosts = {
"vaultwarden.railbird.ai" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://[::1]:8222";
};
};
"syncthing.railbird.ai" = {
enableACME = true;
forceSSL = true;
root = "/var/lib/syncthing/railbird";
locations."/" = {
extraConfig = ''
autoindex on;
'';
};
};
"docs.railbird.ai" = {
enableACME = true;
forceSSL = true;
root = "/var/lib/syncthing/railbird/docs";
locations."/" = {
extraConfig = ''
autoindex on;
'';
};
};
};
};
security.acme = {
acceptTerms = true;
defaults.email = "IvanMalison@gmail.com";
};
hardware.enableRedistributableFirmware = true;
myModules.nvidia.enable = true;
@@ -106,11 +49,9 @@
{ device = "/dev/disk/by-uuid/598e9aa1-4940-4410-a2fa-3dfd8b7d2c0d"; }
];
home-manager.sharedModules = [
{
home.stateVersion = "23.11";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.11";
};
networking.hostName = "jimi-hendnix";

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, forEachUser, ... }:
{
imports = [
@@ -201,9 +201,7 @@
system.stateVersion = "23.05";
home-manager.sharedModules = [
{
home.stateVersion = "23.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.05";
};
}

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, inputs, ... }:
{ config, lib, pkgs, inputs, forEachUser, ... }:
{
imports = [
../configuration.nix
@@ -62,11 +62,9 @@
services.xrdp.defaultWindowManager = "startplasma-x11";
services.xrdp.openFirewall = true;
home-manager.sharedModules = [
{
home.stateVersion = "23.11";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.11";
};
system.stateVersion = "23.11";
}

View File

@@ -1,32 +1,11 @@
{ config, lib, pkgs, inputs, orgAgendaApiContainer ? null, orgAgendaApiImageName ? "org-agenda-api", ... }:
{ config, lib, pkgs, forEachUser, ... }:
{
imports = [
../configuration.nix
inputs.agenix.nixosModules.default
];
networking.hostName = "railbird-sf";
# org-agenda-api hosting with nginx + Let's Encrypt
# Separate secrets for org-agenda-api: auth password (env format) and SSH key (raw file)
age.secrets.org-api-auth-password = {
file = ../secrets/org-api-auth-password.age;
};
age.secrets.org-api-ssh-key = {
file = ../secrets/org-api-ssh-key.age;
mode = "0400"; # Restrictive permissions for SSH key
};
services.org-agenda-api-host = {
enable = true;
domain = "rbsf.tplinkdns.com";
extraDomains = [ "org-agenda-api.rbsf.railbird.ai" ];
containerImage = orgAgendaApiImageName;
containerImageFile = orgAgendaApiContainer;
secretsFile = config.age.secrets.org-api-auth-password.path;
sshKeyFile = config.age.secrets.org-api-ssh-key.path;
};
hardware.enableRedistributableFirmware = true;
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
@@ -50,8 +29,10 @@
nvidiaSettings = true;
};
features.full.enable = false;
myModules.base.enable = true;
myModules.desktop.enable = true;
myModules.xmonad.enable = false;
myModules.code.enable = true;
myModules.syncthing.enable = true;
myModules.fonts.enable = true;
@@ -86,11 +67,9 @@
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
home-manager.sharedModules = [
{
home.stateVersion = "23.11";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.11";
};
system.stateVersion = "23.11";
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ lib, pkgs, forEachUser, ... }:
{
imports = [
@@ -93,11 +93,9 @@
# services.xrdp.openFirewall = true;
system.stateVersion = "20.03";
home-manager.sharedModules = [
{
home.stateVersion = "21.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "21.05";
};
# users.extraUsers.dean.home = "/shared/dean";
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, ... }:
{ lib, pkgs, config, inputs, forEachUser, ... }:
{
imports = [
../configuration.nix
@@ -18,9 +18,7 @@
wsl.defaultUser = "imalison";
system.stateVersion = "22.05";
home-manager.sharedModules = [
{
home.stateVersion = "22.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "22.05";
};
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ lib, pkgs, forEachUser, ... }:
{
imports = [
@@ -83,11 +83,9 @@
# services.xrdp.openFirewall = true;
system.stateVersion = "20.03";
home-manager.sharedModules = [
{
home.stateVersion = "21.05";
}
];
home-manager.users = forEachUser {
home.stateVersion = "21.05";
};
# users.extraUsers.dean.home = "/shared/dean";
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, ... }:
{ lib, pkgs, config, inputs, forEachUser, ... }:
{
imports = [
../configuration.nix
@@ -11,11 +11,9 @@
wsl.defaultUser = "imalison";
system.stateVersion = "23.11"; # Did you read the comment?
home-manager.sharedModules = [
{
home.stateVersion = "23.11";
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.11";
};
programs.gnupg = {
agent = {

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, inputs, ... }:
{ config, lib, pkgs, inputs, forEachUser, ... }:
{
imports = [
@@ -6,6 +6,7 @@
inputs.nixos-hardware.nixosModules.asus-rog-strix-g834jzr
];
hardware.nvidia.open = true;
myModules.base.enable = true;
myModules.desktop.enable = true;
myModules.xmonad.enable = true;
@@ -21,15 +22,10 @@
myModules.tts.enable = false;
hardware.enableRedistributableFirmware = true;
# nixpkgs.config.cudaSupport = true;
boot.loader.systemd-boot.configurationLimit = 5;
environment.systemPackages = with pkgs; [
android-studio
gimp
inkscape
];
services.synergy.server = {
@@ -39,7 +35,7 @@
};
services.matter-server = {
enable = false;
enable = true;
logLevel = "debug";
extraArgs = ["--bluetooth-adapter=0" "--enable-test-net-dcl"];
};
@@ -50,15 +46,11 @@
services.xserver.dpi = 96;
boot.kernelPackages = pkgs.linuxPackages_latest;
# See https://github.com/NixOS/nixpkgs/issues/467814 for why this was needed
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.beta;
boot.initrd.availableKernelModules = [ "vmd" "xhci_pci" "thunderbolt" "nvme" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ "nvidia" "nvidia_drm" "nvidia_uvm" "nvidia_modeset" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
hardware.nvidia.powerManagement.enable = true;
hardware.nvidia.prime.offload.enable = lib.mkForce false;
hardware.nvidia.prime.sync.enable = lib.mkForce true;
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
@@ -76,7 +68,6 @@
swapDevices = [
{ device = "/dev/disk/by-uuid/27f277a0-b552-43a0-904d-625e48922bb9"; }
{ device = "/swapfile"; size = 16384; } # size is in MiB (adds 16 GiB)
];
networking.hostName = "strixi-minaj";
@@ -84,15 +75,9 @@
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
hardware.cpu.intel.updateMicrocode = lib.mkDefault true;
home-manager.sharedModules = [
{
home.stateVersion = "23.05";
xdg.configFile."waybar/disks".text = ''
# One mountpoint per line (comments with # are ignored).
/
'';
}
];
home-manager.users = forEachUser {
home.stateVersion = "23.05";
};
system.stateVersion = "23.05";
}

View File

@@ -1,4 +1,4 @@
{ inputs, specialArgs, config, lib, realUsers, ... }:
{ inputs, specialArgs, config, lib, ... }:
{
imports = [
inputs.home-manager.nixosModules.home-manager
@@ -11,7 +11,6 @@
};
};
config = {
home-manager.users = lib.genAttrs realUsers (_: {});
home-manager.extraSpecialArgs = {
nixos = {
inherit specialArgs config;
@@ -20,7 +19,6 @@
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.backupFileExtension = "backup";
home-manager.sharedModules = [ ./home-manager.nix ];
nix = rec {
extraOptions = ''
@@ -34,15 +32,11 @@
"https://cache.nixos.org"
"https://cuda-maintainers.cachix.org"
"https://ai.cachix.org"
"https://codex-cli.cachix.org"
"https://claude-code.cachix.org"
];
trusted-public-keys = [
"cache.railbird.ai:KhnvcouxtIU2zxUcjJsm4bUK3o1S3p8xMf9qfZGF7/A="
"cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E="
"ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc="
"codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing="
"claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk="
];
nix-path = nixPath;
};
@@ -56,11 +50,6 @@
# (import ./nvidia-container-toolkit-overlay.nix)
(import ./runc-overlay.nix)
(import ./overlay.nix)
# Use codex and claude-code from dedicated flakes with cachix
(final: prev: {
codex = inputs.codex-cli-nix.packages.${prev.stdenv.hostPlatform.system}.default;
claude-code = inputs.claude-code-nix.packages.${prev.stdenv.hostPlatform.system}.default;
})
] ++ (if config.imalison.nixOverlay.enable then [ inputs.nix.overlays.default ] else []);
# Allow all the things

View File

@@ -16,8 +16,8 @@ makeEnable config "myModules.nvidia" false {
};
hardware.nvidia.open = true;
hardware.graphics.enable32Bit = true;
hardware.graphics.extraPackages = [ config.hardware.nvidia.package.out ];
hardware.graphics.extraPackages32 = [ config.hardware.nvidia.package.lib32 ];
hardware.graphics.extraPackages = [ config.boot.kernelPackages.nvidia_x11.out ];
hardware.graphics.extraPackages32 = [ config.boot.kernelPackages.nvidia_x11.lib32 ];
services.xserver = {
videoDrivers = [ "nvidia" ];
};

Some files were not shown because too many files have changed in this diff Show More