20 Commits

Author SHA1 Message Date
Joe Frikker c9394673db A little more prose 2026-09-09 09:48:50 -04:00
Joe Frikker 48ed1287d7 A little prose 2026-09-04 17:07:17 -04:00
Joe Frikker 9713bb6ae2 Removing perspective 2026-09-04 16:53:46 -04:00
Joe Frikker afdbf7cfa2 buffer-terminator 2026-09-04 16:41:54 -04:00
Joe Frikker 9e9d2bbfcc No more right side window 2026-09-04 14:36:52 -04:00
Joe Frikker 3682c1ad10 flake update 2026-08-19 21:32:09 -04:00
Joe Frikker 5f639e747d kitty? 2026-08-19 17:39:50 -04:00
Joe Frikker 3159d20e6d wip 2026-08-06 16:22:57 -04:00
Joe Frikker e6240591c9 font etc 2026-07-24 17:08:51 -04:00
Joe Frikker 5f96f98158 wip 2026-07-15 15:21:15 -04:00
Joe Frikker a1abf5b4a1 wip 2026-07-10 00:11:54 -04:00
Joe Frikker ba8ef4f585 wip 2026-07-09 23:36:36 -04:00
Joe Frikker eb057a2c3a perspective 2026-07-07 23:10:02 -04:00
Joe Frikker 8effe5f401 popper 2026-07-07 22:48:21 -04:00
Joe Frikker 8fae2a5338 wip 2026-07-07 15:01:03 -04:00
Joe Frikker 1c379cc4a3 wip 2026-07-02 15:19:56 -04:00
Joe Frikker 69f3fa445b Fewer sbcl packages 2026-06-30 16:19:08 -04:00
Joe Frikker 6c1b0faea4 format-all 2026-06-30 16:16:57 -04:00
Joe Frikker c68e79ca4f Bufferlo, and re-add God mode 2026-06-30 15:42:28 -04:00
Joe Frikker af8a00ab5b Flake update, and fixing side window sizes 2026-06-27 16:16:41 -04:00
3 changed files with 631 additions and 263 deletions
Generated
+38 -54
View File
@@ -1,20 +1,23 @@
{ {
"nodes": { "nodes": {
"flake-parts": { "claude-code": {
"inputs": { "inputs": {
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs": [
"nixpkgs"
],
"systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1765835352, "lastModified": 1787169825,
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=", "narHash": "sha256-3MmWHAzeoFHfwjUCQC01olBN+MC4xoSuR7D0bpPr+EE=",
"owner": "hercules-ci", "owner": "sadjow",
"repo": "flake-parts", "repo": "claude-code-nix",
"rev": "a34fae9c08a15ad73f295041fec82323541400a9", "rev": "f575914388682670df73e80c9caf82063b659699",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "hercules-ci", "owner": "sadjow",
"repo": "flake-parts", "repo": "claude-code-nix",
"type": "github" "type": "github"
} }
}, },
@@ -25,11 +28,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779969295, "lastModified": 1787176219,
"narHash": "sha256-HwIJ3tOcwSMiV75L7KqJXciXR9UfT+d7rwOZMX7cTnA=", "narHash": "sha256-djoRr6jBpe35q/0JwAvXpFXg1Ktf+X54NU2RLR7wnHw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "61e2c9659324181e0f0ed911958c536333b1d4f6", "rev": "c53d643b3737e2fcd04e6cb3b3580ef50b2087a0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -39,25 +42,6 @@
"type": "github" "type": "github"
} }
}, },
"kube": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1767247330,
"narHash": "sha256-CxXwzmvAOO07719jzE0Zw14C9r3fQcXfPllLtt5cIzo=",
"rev": "4a4d79a290c92de630e503f395fc8fd709904c1b",
"type": "tarball",
"url": "https://gitea.home-frikker.dedyn.io/api/v1/repos/jfrikker/kube/archive/4a4d79a290c92de630e503f395fc8fd709904c1b.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://gitea.home-frikker.dedyn.io/jfrikker/kube/archive/1.0.1.tar.gz"
}
},
"nix-index-database": { "nix-index-database": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -65,11 +49,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779604987, "lastModified": 1786852476,
"narHash": "sha256-ZQ5z+fVhxYKtIFwtqGp5O0PD84BM1riASvqDaN5Xs+s=", "narHash": "sha256-IM5CYtf86W4w8eUPpKcY/LpdHElmVBtJhaKnoTKxZEA=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "8fba98c80b48fa013820e0163c5096922fea4ddd", "rev": "c7962dc97b45129df8d751bedaf37beb5a17706e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -80,42 +64,42 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1779560665, "lastModified": 1787101114,
"narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=", "narHash": "sha256-gwrPcFf/rDjHPaVflbDZ040ZDmBTRj/7+s8ZmE2SaIM=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786", "rev": "b18a4b905f8d028dc4476412e6d6891728695379",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-unstable", "ref": "nixos-26.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-lib": {
"locked": {
"lastModified": 1765674936,
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"claude-code": "claude-code",
"home-manager": "home-manager", "home-manager": "home-manager",
"kube": "kube",
"nix-index-database": "nix-index-database", "nix-index-database": "nix-index-database",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
},
"systems": {
"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", "root": "root",
+13 -8
View File
@@ -3,15 +3,20 @@
inputs = { inputs = {
# Specify the source of Home Manager and Nixpkgs. # Specify the source of Home Manager and Nixpkgs.
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-26.05";
claude-code = {
url = "github:sadjow/claude-code-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = { home-manager = {
url = "github:nix-community/home-manager/master"; url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
kube = { # kube = {
url = "https://gitea.home-frikker.dedyn.io/jfrikker/kube/archive/1.0.1.tar.gz"; # url = "https://gitea.home-frikker.dedyn.io/jfrikker/kube/archive/1.0.1.tar.gz";
inputs.nixpkgs.follows = "nixpkgs"; # inputs.nixpkgs.follows = "nixpkgs";
}; # };
nix-index-database = { nix-index-database = {
url = "github:nix-community/nix-index-database"; url = "github:nix-community/nix-index-database";
@@ -19,7 +24,7 @@
}; };
}; };
outputs = { nixpkgs, home-manager, kube, nix-index-database, ... }: outputs = { nixpkgs, home-manager, claude-code, nix-index-database, ... }:
let modules-for-system = pkgs: pkgs.stdenv.mkDerivation { let modules-for-system = pkgs: pkgs.stdenv.mkDerivation {
name = "home-manager-modules"; name = "home-manager-modules";
src = pkgs.lib.fileset.toSource { src = pkgs.lib.fileset.toSource {
@@ -62,7 +67,7 @@
home.packages = [ pkgs.pinentry_mac ]; home.packages = [ pkgs.pinentry_mac ];
}]; }];
extraSpecialArgs = { kube = kube.packages.aarch64-darwin.default; }; extraSpecialArgs = { claude-code = claude-code.packages.aarch64-darwin.default; };
}; };
homeConfigurations.home = homeConfigurations.home =
let pkgs = nixpkgs.legacyPackages.x86_64-linux; let pkgs = nixpkgs.legacyPackages.x86_64-linux;
@@ -82,7 +87,7 @@
home.homeDirectory = "/home/jfrikker"; home.homeDirectory = "/home/jfrikker";
}]; }];
extraSpecialArgs = { kube = kube.packages.x86_64-linux.default; }; extraSpecialArgs = { claude-code = claude-code.packages.x86_64-linux.default; };
}; };
packages.aarch64-darwin.default = modules-for-system nixpkgs.legacyPackages.aarch64-darwin; packages.aarch64-darwin.default = modules-for-system nixpkgs.legacyPackages.aarch64-darwin;
}; };
+508 -129
View File
@@ -54,10 +54,8 @@ carefully so it doesn't get carried away...
alexandria alexandria
cl-markup cl-markup
cl-mock cl-mock
cl-rdkafka
clack clack
clack-handler-woo clack-handler-woo
dbd-mysql
dbi dbi
defstar defstar
dexador dexador
@@ -168,14 +166,10 @@ These are the other programs I have installed globally. A few (like ~awscli~, ~m
are still Redbook-specific; ideally I'd find another way to install them. are still Redbook-specific; ideally I'd find another way to install them.
#+BEGIN_SRC nix :tangle target/redbook/other-packages.nix #+BEGIN_SRC nix :tangle target/redbook/other-packages.nix
{pkgs, kube, ...}: {pkgs, ...}:
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
aws-iam-authenticator postgresql
awscli2
kube
kubectl
mariadb.client
openssh openssh
]; ];
@@ -194,7 +188,7 @@ These programs require a full desktop environment:
nerd-fonts.symbols-only nerd-fonts.symbols-only
(iosevka-bin.override { variant = "Aile"; }) (iosevka-bin.override { variant = "Aile"; })
(iosevka-bin.override { variant = "Etoile"; }) (iosevka-bin.override { variant = "Etoile"; })
(iosevka-bin.override { variant = "SGr-IosevkaTerm"; }) (iosevka-bin.override { variant = "SGr-IosevkaTermSS14"; })
keymapp keymapp
proton-pass proton-pass
wireshark wireshark
@@ -206,7 +200,15 @@ These programs require a full desktop environment:
{pkgs, ...}: {pkgs, ...}:
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
slack linear
(slack.overrideAttrs {
version = "4.50.143";
src = pkgs.fetchurl {
url = "https://downloads.slack-edge.com/desktop-releases/mac/arm64/4.50.143/Slack-4.50.143-macOS.dmg";
hash = "sha256-f5oYi8NPKXWpDcowFYMUjptbQs4V9hK2bm1TuaQeJn0=";
};
})
teams
]; ];
} }
#+END_SRC #+END_SRC
@@ -316,6 +318,7 @@ We all know what ~git~ does.
settings.user.name = "Joe Frikker"; settings.user.name = "Joe Frikker";
settings.user.email = "joe@redbookcattle.com"; settings.user.email = "joe@redbookcattle.com";
settings.github.user = "joe@redbookcattle.com"; settings.github.user = "joe@redbookcattle.com";
settings.merge.conflictstyle = "zdiff3";
}; };
programs.delta = { programs.delta = {
@@ -342,7 +345,7 @@ The best text editor ever? Heresy!
auto-save.after-delay.timeout = 1000; auto-save.after-delay.timeout = 1000;
cursorline = true; cursorline = true;
idle-timeout = 0; idle-timeout = 0;
rulers = [100]; rulers = [120];
text-width = 100; text-width = 100;
lsp.goto-reference-include-declaration = false; lsp.goto-reference-include-declaration = false;
cursor-shape.insert = "bar"; cursor-shape.insert = "bar";
@@ -503,6 +506,7 @@ Then the real lua config:
#+BEGIN_SRC lua #+BEGIN_SRC lua
local config = {} local config = {}
config.default_prog = { '/Users/jfrikker/.nix-profile/bin/zsh', '-l' } config.default_prog = { '/Users/jfrikker/.nix-profile/bin/zsh', '-l' }
config.font = wezterm.font 'Iosevka Term SS14'
config.font_size = 13.0 config.font_size = 13.0
-- config.font = wezterm.font("JetBrains Mono") -- config.font = wezterm.font("JetBrains Mono")
config.inactive_pane_hsb = { config.inactive_pane_hsb = {
@@ -660,7 +664,7 @@ Now we'll set up some keybindings:
key = "g", key = "g",
mods = "CMD", mods = "CMD",
action = wezterm.action.SpawnCommandInNewTab { action = wezterm.action.SpawnCommandInNewTab {
args = { wezterm.home_dir .. "/.nix-profile/bin/zsh", "-l", "-c", "lazygit" } args = { wezterm.home_dir .. "/.nix-profile/bin/zsh", "-l", "-i", "-c", "lazygit" }
} }
}, },
{ {
@@ -690,6 +694,48 @@ Now we'll set up some keybindings:
end end
#+END_SRC #+END_SRC
** Kitty
#+BEGIN_SRC nix :tangle target/desktop/kitty.nix
{pkgs, ...}: {
programs.kitty = {
enable = true;
font = {
name = "Iosevka Term SS14";
package = pkgs.iosevka-bin.override { variant = "SGr-IosevkaTermSS14"; };
size = 13;
};
themeFile = "Catppuccin-Frappe";
keybindings = {
"ctrl+1" = "goto_tab 1";
"ctrl+2" = "goto_tab 2";
"ctrl+3" = "goto_tab 3";
"ctrl+4" = "goto_tab 4";
"ctrl+5" = "goto_tab 5";
"ctrl+6" = "goto_tab 6";
"ctrl+7" = "goto_tab 7";
"ctrl+8" = "goto_tab 8";
"ctrl+9" = "goto_tab 9";
};
};
}
#+END_SRC
** Ghostty
#+BEGIN_SRC nix :tangle target/desktop/ghostty.nix
{pkgs, ...}: {
programs.ghostty = {
enable = true;
package = pkgs.ghostty-bin;
settings = {
adjust-cell-height = "15%";
font-family = "Iosevka Term SS14";
font-size = 13;
};
};
}
#+END_SRC
** Zsh ** Zsh
This is my default shell for now. Unfortunately, nix requires a posix-compliant shell, so bash or This is my default shell for now. Unfortunately, nix requires a posix-compliant shell, so bash or
@@ -732,9 +778,10 @@ Actually, nix *really* requires ~bash~. This is a plugin that allows using zsh f
** Claude Code ** Claude Code
#+BEGIN_SRC nix :tangle target/base/claude-code.nix #+BEGIN_SRC nix :tangle target/base/claude-code.nix
{ {claude-code, ...}: {
programs.claude-code = { programs.claude-code = {
enable = true; enable = true;
package = claude-code;
}; };
} }
#+END_SRC #+END_SRC
@@ -782,10 +829,12 @@ These are just some general settings that apply everywhere. First, a few package
programs.emacs = { programs.emacs = {
enable = true; enable = true;
extraPackages = epkgs: with epkgs; [ extraPackages = epkgs: with epkgs; [
ace-window
doom-modeline doom-modeline
free-keys
ligature ligature
mixed-pitch mixed-pitch
ace-window popper
]; ];
extraConfig = builtins.readFile ./emacs-global.el; extraConfig = builtins.readFile ./emacs-global.el;
}; };
@@ -795,20 +844,76 @@ These are just some general settings that apply everywhere. First, a few package
Turn off some default settings that I don't find useful. Turn off some default settings that I don't find useful.
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(setopt save-interprogram-paste-before-kill t)
(setopt enable-recursive-minibuffers t)
(setopt line-spacing 0.15)
(setopt mouse-wheel-tilt-scroll t)
(setq-default truncate-lines t)
(setopt tab-bar-show nil)
(tab-bar-mode)
#+END_SRC
Don't show the welcome screen, and keep the scratch buffer empty by default. These are not useful
after you've started emacs more than a few times.
#+begin_src elisp
(setopt inhibit-startup-screen t) (setopt inhibit-startup-screen t)
(setopt initial-scratch-message nil) (setopt initial-scratch-message nil)
#+end_src
Turn off all the ugly graphical crap.
#+begin_src elisp
(menu-bar-mode -1) (menu-bar-mode -1)
(scroll-bar-mode -1) (scroll-bar-mode -1)
(tool-bar-mode -1) (tool-bar-mode -1)
#+end_src
I don't find emacs's backup files useful, and they seem to litter my directories. I could maybe see
a use if I wasn't using git. But, git is so easy to use, that I pretty much use it everywhere. I
don't need a poor man's local history.
Also, why do I have to set so many variables just to get emacs to stop putting extra files
everywhere?
#+begin_src elisp
(setopt make-backup-files nil) (setopt make-backup-files nil)
(setopt split-width-threshold 200) (setopt create-lockfiles nil)
(setopt split-height-threshold nil) (setopt auto-save-default nil)
(setopt display-buffer-base-action #+end_src
'((display-buffer-reuse-window display-buffer-same-window
display-buffer-in-previous-window Turn on ~view-mode~ automatically when the buffer is read-only. This just helps out with navigation
display-buffer-use-some-window))) a bit. I almost want to open files read-only by default, just so I can use ~view-mode~ (maybe with
some other keybindings) all the time. But, I think one more invisible flag to manage is a bit much.
#+begin_src elisp
(setopt view-read-only t) (setopt view-read-only t)
#+END_SRC #+end_src
I don't really do anything with sentences. But, I also never put two spaces after a period. So, at
least this setting is correct.
#+begin_src elisp
(setopt sentence-end-double-space nil)
#+end_src
I kill whole lines *way* more than partial lines. If the cursor is at the front of a line, this will
just kill the whole line instead of requiring two ~C-k C-k~ presses to make it happen. I'm not sure
when I'd ever want it to kill the line *without* the trailing newline, but I guess the one time ever
that I do, I'll have to press two more keys :(
#+begin_src elisp
(setopt kill-whole-line t)
#+end_src
Show column numbers in the modeline. Now that I think about it, I'm not sure why I want this. I
guess I could try turning it off someday?
#+begin_src elisp
(column-number-mode t)
#+end_src
Make sure which-key mode is always on. The on-the-fly keymap help it gives is indespensable. Make sure which-key mode is always on. The on-the-fly keymap help it gives is indespensable.
@@ -838,23 +943,13 @@ already indented, then try to complete the thing at point." Recommended by [[htt
#+END_SRC #+END_SRC
Set the cursor to be a bar. I'm not sure what the benefit would be of a block cursor, since the Set the cursor to be a bar. I'm not sure what the benefit would be of a block cursor, since the
current character isn't really "selected" like it would be in Helix. When I had God mode set up, I current character isn't really "selected" like it would be in Helix. I switch this to a box when in
switched to a block cursor during normal mode, just because I was so used to it from Helix and god mode / read-only buffers, like vim would.
Vim. Now, I don't think there's really a need to ever switch.
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(setq-default cursor-type 'bar) (setq-default cursor-type 'bar)
#+END_SRC #+END_SRC
Emacs is supposed to be all about automation (maybe?). There's basically never a case where I don't
want changes I've made to be immediately saved to disk. So let's have Emacs do that. There's still a
fairly long (~5 sec) delay before changes are saved, which is kind of annoying. Maybe I'll look into
that at some point?
#+BEGIN_SRC elisp
; (auto-save-visited-mode)
#+END_SRC
Repeat-mode takes care of eliminating some annoying duplicate keypresses. I mostly use repeat-mode Repeat-mode takes care of eliminating some annoying duplicate keypresses. I mostly use repeat-mode
for two-character commands that need to be repeated; ~devil~ also has some single-key-with-modifier for two-character commands that need to be repeated; ~devil~ also has some single-key-with-modifier
repeats set up that only apply in that mode. repeats set up that only apply in that mode.
@@ -932,13 +1027,18 @@ Set up a few project- / workspace-related key bindings.
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(bind-keys ("s-f" . project-find-file) (bind-keys ("s-f" . project-find-file)
("s-F" . project-switch-project)) ("s-F" . project-switch-project)
;; ("s-s" . persp-switch)
)
(with-eval-after-load 'tab-bar (with-eval-after-load 'tab-bar
(bind-keys :map tab-bar-mode-map (bind-keys :map tab-bar-mode-map
("s-s" . tab-bar-switch-to-tab))) ("s-s" . tab-bar-switch-to-tab)))
#+END_SRC #+END_SRC
#+RESULTS:
: tab-bar-switch-to-tab
Don't run a server. I'm not using this, I can always turn it back on if I need to. Don't run a server. I'm not using this, I can always turn it back on if I need to.
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
@@ -955,7 +1055,7 @@ less so?
I'm trying this out. This disables visual selections. It's bold, which is why I like it :) I'm trying this out. This disables visual selections. It's bold, which is why I like it :)
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
;; (transient-mark-mode -1) (transient-mark-mode -1)
#+END_SRC #+END_SRC
I use tabs to manage multiple "workspaces". I don't tie a project to a tab or anything; often fixing I use tabs to manage multiple "workspaces". I don't tie a project to a tab or anything; often fixing
@@ -987,49 +1087,222 @@ windows. I place windows in the bottom or on the right mostly depending on how w
content to be. content to be.
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(setq display-buffer-alist (defun jf/window-children (window)
'(((or "\\*Flymake diagnostics .*" (let ((result nil)
(child (window-child window)))
(while child
(push child result)
(setq child (window-next-sibling child)))
(reverse result)))
(defun jf/window-main-root (&optional frame)
"Return FRAME's main (non-side) window or window subtree."
(let* ((root (frame-root-window (or frame (selected-frame))))
(children (jf/window-children root)))
(if (seq-some (lambda (w) (window-parameter w 'window-side)) children)
(seq-find (lambda (w) (not (window-parameter w 'window-side))) children)
root)))
(defun jf/window-leaves (window)
"Return the live leaf windows in WINDOW's subtree."
(if (window-live-p window)
(list window)
(mapcan #'jf/window-leaves (jf/window-children window))))
(defun jf/topright-window (windows)
"Return whichever of WINDOWS sits furthest up, then furthest right."
(car (sort (copy-sequence windows)
(lambda (a b)
(let ((top-a (nth 1 (window-edges a)))
(top-b (nth 1 (window-edges b))))
(if (= top-a top-b)
(> (nth 0 (window-edges a)) (nth 0 (window-edges b)))
(< top-a top-b)))))))
(defun jf/display-buffer-right (buffer alist)
"Display BUFFER on the right of the main editing area.
Applies three rules, based on the shape of the frame's non-side windows:
1. One window -> split it and show BUFFER in the new right window.
2. Two windows side-by-side -> show BUFFER in the right one. If the
right window is selected, swap the two windows first (keeping
focus on the buffer that was active) so BUFFER doesn't evict it.
3. Any other layout -> show BUFFER in the upper-rightmost window."
(let ((main (jf/window-main-root)))
(cond
((window-live-p main)
(let* ((new (split-window main nil 'right))
(width (max 1 (- (frame-width) 120)))
(delta (window-resizable new (- width (window-width new)) t)))
(window-resize new delta t)
(window--display-buffer buffer new 'window alist)))
((and (window-left-child main)
(= (length (jf/window-children main)) 2)
(seq-every-p #'window-live-p (jf/window-children main)))
(let* ((left (window-left-child main))
(right (window-next-sibling left)))
(when (eq (selected-window) right)
(window-swap-states left right)
(select-window left))
(window--display-buffer buffer right 'reuse alist)))
(t
(window--display-buffer buffer (jf/topright-window (jf/window-leaves main)) 'reuse alist)))))
(setopt popper-reference-buffers
'("\\*Flymake diagnostics .*"
"\\*Embark Export: .*" "\\*Embark Export: .*"
"\\*Embark Collect .*" "\\*Embark Collect .*"
"\\*xref\\*" "\\*xref\\*"
"\\*compilation\\*" "\\*compilation\\*"
"\\*pnpm:.*"
"\\*sly-mrepl *" "\\*sly-mrepl *"
"\\*Messages\\*"
"\\*lispy-message\\*" "\\*lispy-message\\*"
"\\*EGLOT connections\\*"
"\\*trace-output\\*"
"\\*occur\\*" "\\*occur\\*"
".*eshell\\*") ".*eshell\\*"
(display-buffer-in-side-window) "\\*SQL: .*"
(side . bottom)
(slot . 0)
(window-height . 0.33)
(window-parameters (no-delete-other-windows . t)
(no-other-window . t)))
((or "magit: *"
"magit-revision: .*" "magit-revision: .*"
"magit-log*"
"\\*eldoc\\*"
"\\*Help\\*" "\\*Help\\*"
"\\*rustfmt\\*" "\\*rustfmt\\*"
"\\*slack: .*" "\\*slack: .*"
"\\*forge: .*" "\\*forge: .*"
"new-pullreq" "new-pullreq"
"\\*claude:.*" "\\*claude:.*"
"\\*Man .*") "\\*Man .*"
(display-buffer-reuse-window display-buffer-in-side-window) "\\*List .*"
(side . right) "\\*eldoc\\*"))
(setopt popper-display-control nil)
(popper-mode)
(popper-echo-mode)
(bind-keys ("C-q" . popper-toggle)
("C-;" . popper-cycle))
(defvar jf/fullscreen-popup--param 'jf/fullscreen-saved-configuration
"Key used to stash the window configuration a fullscreen popup replaced.
Stored per-tab when `tab-bar-mode' is active, otherwise as a plain frame
parameter; see `jf/tab-or-frame-parameter'.")
(defvar-local jf/fullscreen-popup-p nil
"Non-nil in a buffer currently being displayed as a fullscreen popup.")
(defun jf/current-tab-cell (&optional frame)
"Return FRAME's current tab's raw data cell, or nil without `tab-bar-mode'."
(and (bound-and-true-p tab-bar-mode)
(assq 'current-tab (tab-bar-tabs frame))))
(defun jf/tab-or-frame-parameter (parameter &optional frame)
"Like `frame-parameter', but scoped to FRAME's selected tab when tabs are in use.
A plain frame parameter is shared by every tab on that frame, which is wrong
for state like `jf/fullscreen-popup--param': switching tabs swaps in an
entirely different window layout, so \"the layout to restore\" has to travel
with the tab, not the frame."
(if-let ((tab (jf/current-tab-cell frame)))
(alist-get parameter tab)
(frame-parameter frame parameter)))
(defun jf/set-tab-or-frame-parameter (parameter value &optional frame)
"Set PARAMETER to VALUE, scoped like `jf/tab-or-frame-parameter'."
(if-let ((tab (jf/current-tab-cell frame)))
(let ((cell (assq parameter tab)))
(if cell
(setcdr cell value)
(setcdr tab (cons (cons parameter value) (cdr tab)))))
(set-frame-parameter frame parameter value)))
(defun jf/display-buffer-fullscreen (buffer alist)
"Display BUFFER, deleting other windows, saving the prior layout.
Intended for use in `display-buffer-alist' for popups (e.g. Magit
status/log) that should take over the frame while displayed, but
restore the previous window configuration once closed via either
`q' or `popper-toggle' -- both end up calling `quit-window', which
is where the restore actually happens; see
`jf/quit-window-restore-fullscreen'."
(unless (jf/tab-or-frame-parameter jf/fullscreen-popup--param)
(jf/set-tab-or-frame-parameter jf/fullscreen-popup--param
(current-window-configuration)))
(when-let ((window (or (display-buffer-reuse-window buffer alist)
(display-buffer-same-window buffer alist)
(display-buffer-pop-up-window buffer alist)
(display-buffer-use-some-window buffer alist))))
(let ((ignore-window-parameters t))
(delete-other-windows window))
(with-current-buffer buffer
(setq jf/fullscreen-popup-p t))
window))
(defun jf/quit-window-restore-fullscreen (orig-fn &optional kill window)
"Restore the saved window configuration after quitting a fullscreen popup.
Advice around `quit-window' so both `q' (which Magit and other
special-mode buffers bind to buffer-quitting commands that call
`quit-window') and Popper's close/toggle commands (which also call
`quit-window' directly) trigger the restore. Only restores once the
last fullscreen popup on the tab (or frame, without `tab-bar-mode')
has closed, so opening one fullscreen popup from within another
falls back to the outer one first."
(let* ((window (or window (selected-window)))
(was-fullscreen (buffer-local-value 'jf/fullscreen-popup-p
(window-buffer window)))
(frame (window-frame window)))
(funcall orig-fn kill window)
(when (and was-fullscreen
(not (and (window-live-p window)
(buffer-local-value 'jf/fullscreen-popup-p
(window-buffer window))))
(jf/tab-or-frame-parameter jf/fullscreen-popup--param frame))
(let ((conf (jf/tab-or-frame-parameter jf/fullscreen-popup--param frame)))
(jf/set-tab-or-frame-parameter jf/fullscreen-popup--param nil frame)
(set-window-configuration conf)))))
(advice-add 'quit-window :around #'jf/quit-window-restore-fullscreen)
(setopt split-width-threshold 200)
(setopt split-height-threshold nil)
(setopt display-buffer-base-action
'((display-buffer-reuse-window display-buffer-same-window
display-buffer-in-previous-window
display-buffer-use-some-window)))
(setq display-buffer-alist
'(((or "magit: *"
"magit-log*"
"\\*Messages\\*"
"\\*trace-output\\*"
"\\*EGLOT connections\\*")
(jf/display-buffer-fullscreen))
((or "\\*Flymake diagnostics .*"
"\\*Embark Export: .*"
"\\*Embark Collect .*"
"\\*xref\\*"
"\\*compilation\\*"
"\\*pnpm:.*"
"\\*sly-mrepl *"
"\\*lispy-message\\*"
"\\*occur\\*"
".*eshell\\*"
"\\*SQL: .*")
(display-buffer-in-side-window)
(side . bottom)
(slot . 0) (slot . 0)
(window-width . 0.5) (window-height . 0.33)
(window-parameters (no-delete-other-windows . t) (window-parameters (no-delete-other-windows . t)
(no-other-window . t))) (no-other-window . t)))
("\\*Embark Actions\\*" ((or "magit-revision: .*"
(display-buffer-in-side-window) "\\*Help\\*"
(side . right) "\\*rustfmt\\*"
(slot . -1) "\\*slack: .*"
(window-width . 0.5) "\\*forge: .*"
(window-parameters (no-delete-other-windows . t) "new-pullreq"
(no-other-window . t))))) "\\*claude:.*"
"\\*Man .*"
"\\*List .*"
"\\*Embark Actions\\*"
"\\*eldoc\\*")
(jf/display-buffer-right))))
(setopt window-persistent-parameters (setopt window-persistent-parameters
(cl-list* '(no-delete-other-windows . writable) (cl-list* '(no-delete-other-windows . writable)
@@ -1053,6 +1326,8 @@ This configuration affects general text editing, across all modes. First, some p
avy avy
edit-indirect edit-indirect
embark embark
format-all
god-mode
# evil # evil
# evil-collection # evil-collection
# evil-org # evil-org
@@ -1086,6 +1361,21 @@ its own devil-mode-only repeat maps that don't interfere when using normal modif
;; (evil-org-set-key-theme '(navigation insert textobjects additional calendar)) ;; (evil-org-set-key-theme '(navigation insert textobjects additional calendar))
;; (require 'evil-org-agenda) ;; (require 'evil-org-agenda)
;; (evil-org-agenda-set-keys) ;; (evil-org-agenda-set-keys)
(require 'god-mode)
(require 'which-key)
(bind-keys :map god-local-mode-map
("i" . (lambda () (interactive) (god-mode-all -1)))
("z" . repeat))
(bind-keys ("<escape>" . (lambda () (interactive) (god-mode-all 1))))
(defun my-god-mode-update-cursor-type ()
(setq cursor-type (cond
((and (featurep 'org-present) org-present-mode) nil)
((or (and (featurep 'god-mode) god-local-mode) buffer-read-only) 'box)
(t 'bar))))
(add-hook 'post-command-hook 'my-god-mode-update-cursor-type)
(which-key-enable-god-mode-support)
#+END_SRC #+END_SRC
Avy allows jumping to any place on the screen with just a few keystrokes. I've stolen most of these Avy allows jumping to any place on the screen with just a few keystrokes. I've stolen most of these
@@ -1107,10 +1397,17 @@ his article.
(avy-goto-char-timer))) (avy-goto-char-timer)))
(bind-keys (bind-keys
("M-j" . avy-goto-char-timer) ("C-j" . avy-goto-char-timer)
("C-c j" . avy-goto-char-timer) ("M-j" . avy-goto-char-timer-embark)
("M-J" . avy-goto-char-timer-embark)
("C-." . embark-act)) ("C-." . embark-act))
(with-eval-after-load 'lispy
(bind-keys :map lispy-mode-map
("C-j" . avy-goto-char-timer)))
(with-eval-after-load 'org
(bind-keys :map org-mode-map
("C-j" . avy-goto-char-timer)))
#+END_SRC #+END_SRC
Just "silently" wrap when searching at the bottom of a document. Just "silently" wrap when searching at the bottom of a document.
@@ -1143,6 +1440,30 @@ Just "silently" wrap when searching at the bottom of a document.
(bind-keys ("C-x 4 n" . edit-indirect-region)) (bind-keys ("C-x 4 n" . edit-indirect-region))
#+END_SRC #+END_SRC
** Workflow
:PROPERTIES:
:header-args:elisp: :tangle target/desktop/emacs-workflow.el
:END:
#+BEGIN_SRC nix :tangle target/desktop/emacs-workflow.nix
{
programs.emacs = {
enable = true;
extraPackages = epkgs: with epkgs; [
buffer-terminator
];
extraConfig = builtins.readFile ./emacs-workflow.el;
};
}
#+END_SRC
#+BEGIN_SRC elisp
(buffer-terminator-mode 1)
(bind-keys
("s-b" . consult-project-buffer))
#+END_SRC
** Language Support ** Language Support
:PROPERTIES: :PROPERTIES:
:header-args:elisp: :tangle target/desktop/emacs-languages.el :header-args:elisp: :tangle target/desktop/emacs-languages.el
@@ -1154,18 +1475,21 @@ Just "silently" wrap when searching at the bottom of a document.
enable = true; enable = true;
extraPackages = epkgs: with epkgs; [ extraPackages = epkgs: with epkgs; [
consult-eglot consult-eglot
graphql-ts-mode
haskell-ts-mode haskell-ts-mode
jenkinsfile-mode jenkinsfile-mode
jq-mode jq-mode
(lispy.overrideAttrs { (lispy.overrideAttrs {
packageRequires = [ packageRequires = [
ace-window iedit swiper zoutline ace-window iedit swiper zoutline hydra
]; ];
ignoreCompilationError = true; ignoreCompilationError = true;
}) })
# lispyville # lispyville
lua-mode lua-mode
nix-mode nix-mode
pnpm-mode
prisma-ts-mode
rust-mode rust-mode
sly sly
sly-macrostep sly-macrostep
@@ -1196,6 +1520,7 @@ Just "silently" wrap when searching at the bottom of a document.
g.tree-sitter-nix g.tree-sitter-nix
g.tree-sitter-org g.tree-sitter-org
g.tree-sitter-php g.tree-sitter-php
g.tree-sitter-prisma
g.tree-sitter-python g.tree-sitter-python
g.tree-sitter-rust g.tree-sitter-rust
g.tree-sitter-rust-format-args g.tree-sitter-rust-format-args
@@ -1233,7 +1558,7 @@ Show a vertical bar 100 characters out; ideally I don't want lines longer than t
is about the max you can have and still fit two files side-by-side on the screen. is about the max you can have and still fit two files side-by-side on the screen.
#+begin_src elisp #+begin_src elisp
(setq-default fill-column 100) (setq-default fill-column 120)
(defun jf-init-fill-column () (defun jf-init-fill-column ()
(display-fill-column-indicator-mode 1)) (display-fill-column-indicator-mode 1))
@@ -1273,6 +1598,10 @@ available? It seems to work for now anyway...
(advice-add 'prog-fill-reindent-defun :override #'my-prog-fill-reindent-defun)) (advice-add 'prog-fill-reindent-defun :override #'my-prog-fill-reindent-defun))
#+end_src #+end_src
#+BEGIN_SRC elisp
(add-hook 'compilation-filter-hook 'ansi-color-compilation-filter)
#+END_SRC
*** Flymake *** Flymake
#+begin_src elisp #+begin_src elisp
(autoload 'flymake-show-project-diagnostics "flymake") (autoload 'flymake-show-project-diagnostics "flymake")
@@ -1297,6 +1626,7 @@ I don't like UI elements that insert fake text into the file. They mess up the s
(setopt eglot-ignored-server-capabilities '(:inlayHintProvider :semanticTokensProvider)) (setopt eglot-ignored-server-capabilities '(:inlayHintProvider :semanticTokensProvider))
(add-hook 'eglot-managed-mode-hook (lambda () (eglot-inlay-hints-mode -1)) nil t) (add-hook 'eglot-managed-mode-hook (lambda () (eglot-inlay-hints-mode -1)) nil t)
(setopt eglot-code-action-indications nil) (setopt eglot-code-action-indications nil)
(setopt eglot-events-buffer-config '(:size 300000 :format full))
#+END_SRC #+END_SRC
Set up a few useful eglot keys. Set up a few useful eglot keys.
@@ -1341,27 +1671,28 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(setopt inferior-lisp-program "sbcl") (setopt inferior-lisp-program "sbcl")
;; (setopt lispy-compat '(god-mode edebug)) (setopt lispy-compat '(god-mode edebug))
(add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1))) (add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1)))
(add-hook 'lisp-mode-hook (lambda () (lispy-mode 1))) (add-hook 'lisp-mode-hook (lambda () (lispy-mode 1)))
;; (with-eval-after-load 'lispy (add-hook 'lisp-data-mode-hook (lambda () (lispy-mode 1)))
(with-eval-after-load 'lispy
;; (require 'lispyville) ;; (require 'lispyville)
;; (add-hook 'lispy-mode-hook #'lispyville-mode) ;; (add-hook 'lispy-mode-hook #'lispyville-mode)
;; (bind-keys :map lispy-mode-map (bind-keys :map lispy-mode-map
;; ("i" . (lambda () ("i" . (lambda ()
;; (interactive) (interactive)
;; (if (and (featurep 'god-mode) god-global-mode) (if (and (featurep 'god-mode) god-global-mode)
;; (god-mode-all -1) (god-mode-all -1)
;; (special-lispy-tab)))))) (special-lispy-tab))))))
#+END_SRC #+END_SRC
*** Typescript *** Typescript
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(push '("\\.ts\\'" . typescript-mode) auto-mode-alist) (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode))
(push '(typescript-mode . typescript-ts-mode) major-mode-remap-alist) (add-to-list 'major-mode-remap-alist '(typescript-mode . typescript-ts-mode))
(push '("\\.tsx\\'" . tsx-mode) auto-mode-alist) (add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-mode))
(push '(tsx-mode . tsx-ts-mode) major-mode-remap-alist) (add-to-list 'major-mode-remap-alist '(tsx-mode . tsx-ts-mode))
(setopt typescript-ts-mode-indent-offset 4) (setopt typescript-ts-mode-indent-offset 2)
(with-eval-after-load 'typescript-ts-mode (with-eval-after-load 'typescript-ts-mode
(defun my-tsx-ts-mode--indent-compatibility-b893426 () (defun my-tsx-ts-mode--indent-compatibility-b893426 ()
"Indent rules helper, to handle different releases of tree-sitter-tsx. "Indent rules helper, to handle different releases of tree-sitter-tsx.
@@ -1375,6 +1706,52 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
`(((match "<" "jsx_text") parent 0) `(((match "<" "jsx_text") parent 0)
((parent-is "jsx_text") grand-parent typescript-ts-mode-indent-offset))))) ((parent-is "jsx_text") grand-parent typescript-ts-mode-indent-offset)))))
(advice-add 'tsx-ts-mode--indent-compatibility-b893426 :override #'my-tsx-ts-mode--indent-compatibility-b893426)) (advice-add 'tsx-ts-mode--indent-compatibility-b893426 :override #'my-tsx-ts-mode--indent-compatibility-b893426))
(defvar my/edit-indirect-tag-modes
'(("graphql" . graphql-ts-mode)
("gql" . graphql-ts-mode)
("sql" . sql-mode)
("css" . css-mode))
"Map of tagged-template tag names to major modes.")
(defun my/edit-indirect--node-bounds (node)
"Return (BEG . END) for NODE's contents, excluding delimiters."
(cons (1+ (treesit-node-start node))
(1- (treesit-node-end node))))
(defun my/edit-indirect-tagged-template-at-point ()
(interactive)
(let* ((node (treesit-node-at (point)))
(tmpl-node (treesit-parent-until
node
(lambda (n) (equal (treesit-node-type n) "template_string"))))
(str-node (unless tmpl-node
(treesit-parent-until
node
(lambda (n) (equal (treesit-node-type n) "string")))))
(target-node (or tmpl-node str-node)))
(unless target-node
(user-error "Point is not inside a string or template literal"))
(let* ((tagged-node (and tmpl-node (treesit-node-parent tmpl-node)))
(tag-node (and tagged-node
(equal (treesit-node-type tagged-node) "call_expression")
(treesit-node-child-by-field-name tagged-node "function")))
(tag-name (and tag-node (treesit-node-text tag-node t)))
(mode (cond
(tag-name (or (cdr (assoc tag-name my/edit-indirect-tag-modes))
major-mode))
(t 'text-mode)))
(bounds (my/edit-indirect--node-bounds target-node))
(buf (edit-indirect-region (car bounds) (cdr bounds) t)))
(with-current-buffer buf
(funcall mode)))))
(with-eval-after-load 'typescript-ts-mode
(define-key typescript-ts-mode-map (kbd "C-c '") #'my/edit-indirect-tagged-template-at-point)
(define-key tsx-ts-mode-map (kbd "C-c '") #'my/edit-indirect-tagged-template-at-point))
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs '((prisma-ts-mode) "prisma-language-server" "--stdio")))
#+END_SRC #+END_SRC
*** Java *** Java
@@ -1521,11 +1898,10 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
;; ("C-x M-:" . consult-complex-command) ;; ("C-x M-:" . consult-complex-command)
("C-x b" . consult-buffer) ("C-x b" . consult-buffer)
("s-b" . consult-project-buffer)
("s-B" . consult-buffer) ("s-B" . consult-buffer)
("C-x 4 b" . consult-buffer-other-window) ("C-x 4 b" . consult-buffer-other-window)
("C-x 5 b" . consult-buffer-other-frame) ("C-x 5 b" . consult-buffer-other-frame)
("C-x t b" . consult-buffer-other-tab) ;; ("C-x t b" . consult-buffer-other-tab)
("C-x r b" . consult-bookmark) ("C-x r b" . consult-bookmark)
("C-x p b" . consult-project-buffer) ("C-x p b" . consult-project-buffer)
@@ -1570,8 +1946,10 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
consult-ripgrep consult-git-grep consult-grep consult-man consult-ripgrep consult-git-grep consult-grep consult-man
consult-bookmark consult-recent-file consult-xref consult-bookmark consult-recent-file consult-xref
consult-source-bookmark consult-source-file-register consult-source-bookmark consult-source-file-register
consult-source-recent-file consult-source-project-recent-file consult-source-recent-file
consult-source-buffer
;; :preview-key "M-." ;; :preview-key "M-."
consult-source-project-recent-file
:preview-key '(:debounce 0.4 any))) :preview-key '(:debounce 0.4 any)))
(setopt consult-narrow-key "<") ;; "C-+" (setopt consult-narrow-key "<") ;; "C-+"
@@ -1622,6 +2000,8 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
("C-c C" . org-capture) ("C-c C" . org-capture)
("C-c l" . org-id-store-link)) ("C-c l" . org-id-store-link))
(setopt org-babel-load-languages '((emacs-lisp . t) (sql . t)))
(setopt org-confirm-babel-evaluate nil)
(add-hook 'org-mode-hook 'visual-line-mode) (add-hook 'org-mode-hook 'visual-line-mode)
(setopt org-link-keep-stored-after-insertion t (setopt org-link-keep-stored-after-insertion t
org-capture-templates org-capture-templates
@@ -1656,11 +2036,11 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
(set-face-attribute 'org-level-7 nil :font "Iosevka Aile") (set-face-attribute 'org-level-7 nil :font "Iosevka Aile")
(set-face-attribute 'org-level-8 nil :font "Iosevka Aile") (set-face-attribute 'org-level-8 nil :font "Iosevka Aile")
(require 'org-present) (defvar-local my/org-present-face-remapping-cookies nil)
(with-eval-after-load 'org-present
(require 'face-remap) (require 'face-remap)
(require 'visual-fill-column) (require 'visual-fill-column)
(defvar-local my/org-present-face-remapping-cookies nil)
(defun my/org-present-start () (defun my/org-present-start ()
(setq-local my/org-present-face-remapping-cookies nil) (setq-local my/org-present-face-remapping-cookies nil)
;; Tweak font sizes ;; Tweak font sizes
@@ -1712,21 +2092,22 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
) )
(add-hook 'org-present-mode-hook 'my/org-present-start) (add-hook 'org-present-mode-hook 'my/org-present-start)
(add-hook 'org-present-mode-quit-hook 'my/org-present-end) (add-hook 'org-present-mode-quit-hook 'my/org-present-end))
(require 'org-roam) ;; (require 'org-roam)
(bind-keys ("C-c n l" . org-roam-buffer-toggle) ;; (bind-keys ("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find) ;; ("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph) ;; ("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert) ;; ("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)) ;; ("C-c n c" . org-roam-capture))
;; (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))) ;; (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
(org-roam-db-autosync-mode) ;; (org-roam-db-autosync-mode)
(add-hook 'org-mode-hook 'org-modern-mode) (use-package org-modern
:hook org-mode-hook)
(define-key org-mode-map (kbd "C-c C-r") verb-command-map) ;; (define-key org-mode-map (kbd "C-c C-r") verb-command-map)
#+END_SRC #+END_SRC
** Terminal ** Terminal
@@ -1747,7 +2128,9 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
#+END_SRC #+END_SRC
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(eat-eshell-mode) (use-package eat
:commands (eat)
:hook (eshell-load-hook . eat-eshell-mode))
#+END_SRC #+END_SRC
** Slack ** Slack
@@ -1768,32 +2151,16 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
#+END_SRC #+END_SRC
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(setopt lui-time-stamp-format "[%Y-%m-%d %H:%M]") (use-package lui
(setopt slack-render-profile-images-p nil) :defer t
(setopt slack-buffer-function #'switch-to-buffer) :custom
#+END_SRC (lui-time-stamp-format "[%Y-%m-%d %H:%M]"))
** Kubernetes (use-package slack
:PROPERTIES: :commands slack-start
:header-args:elisp: :tangle target/desktop/emacs-kubernetes.el :custom
:END: (slack-render-profile-images-p nil)
(slack-buffer-function #'switch-to-buffer))
#+BEGIN_SRC nix :tangle target/desktop/emacs-kubernetes.nix
{
programs.emacs = {
enable = true;
extraPackages = epkgs: with epkgs; [
kubed
];
extraConfig = builtins.readFile ./emacs-kubernetes.el;
};
}
#+END_SRC
#+BEGIN_SRC elisp
(use-package kubed
:bind-keymap
("s-k" . kubed-prefix-map))
#+END_SRC #+END_SRC
** Ledger ** Ledger
@@ -1827,10 +2194,13 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
#+END_SRC #+END_SRC
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(use-package age
:custom
(setopt age-default-identity "~/source/dotfiles/keys/yubi1age.txt") (setopt age-default-identity "~/source/dotfiles/keys/yubi1age.txt")
(setopt age-default-recipient "~/source/dotfiles/keys/myself.txt") (age-default-recipient "~/source/dotfiles/keys/myself.txt")
:config
(setenv "PINENTRY_PROGRAM" "pinentry-mac") (setenv "PINENTRY_PROGRAM" "pinentry-mac")
(age-file-enable) (age-file-enable))
#+END_SRC #+END_SRC
** Claude Code ** Claude Code
@@ -1845,12 +2215,13 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
enable = true; enable = true;
extraPackages = epkgs: with epkgs; [ extraPackages = epkgs: with epkgs; [
(epkgs.trivialBuild { (epkgs.trivialBuild {
name = "claude-code"; pname = "claude-code";
version = "0.4.5";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "stevemolitor"; owner = "stevemolitor";
repo = "claude-code.el"; repo = "claude-code.el";
rev = "4a9914bd4161eb43f489820f9174c62390e5adc8"; rev = "03199df8b3a1e9cd4857f0851f7a912ba524aff3";
sha256 = "sha256-ISlD6q1hceckry1Jd19BX1MfobHJxng5ulX2gq9f644="; sha256 = "sha256-5QJrWIu4EgnHcOqMwlrs2JBBx7aI9OaSJswesr6Apfk=";
}; };
packageRequires = [ epkgs.inheritenv ]; packageRequires = [ epkgs.inheritenv ];
}) })
@@ -1861,8 +2232,9 @@ for completion. That makes it really annoying to use; don't use yasnippet with e
#+END_SRC #+END_SRC
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(require 'claude-code) (use-package claude-code
(keymap-global-set "C-c c" claude-code-command-map) :bind-keymap ("C-c c" . claude-code-command-map)
:custom (claude-code-optimize-window-resize nil))
#+END_SRC #+END_SRC
* Theme * Theme
I like Catppuccin Frappe as my theme. Let's use it in as many places as we can. I like Catppuccin Frappe as my theme. Let's use it in as many places as we can.
@@ -1953,6 +2325,13 @@ I like Catppuccin Frappe as my theme. Let's use it in as many places as we can.
return config return config
#+END_SRC #+END_SRC
** Ghostty
#+BEGIN_SRC nix :tangle target/desktop/ghostty-theme.nix
{
programs.ghostty.settings.theme = "Catppuccin Frappe";
}
#+END_SRC
** Emacs ** Emacs
:PROPERTIES: :PROPERTIES:
:header-args:elisp: :tangle target/desktop/emacs-theme.el :header-args:elisp: :tangle target/desktop/emacs-theme.el
@@ -1977,7 +2356,7 @@ I like Catppuccin Frappe as my theme. Let's use it in as many places as we can.
;; (set-face-attribute 'default nil :font "JetBrainsMono Nerd Font" :height 130) ;; (set-face-attribute 'default nil :font "JetBrainsMono Nerd Font" :height 130)
;; (set-face-attribute 'fixed-pitch nil :font "JetBrainsMono Nerd Font" :height 130) ;; (set-face-attribute 'fixed-pitch nil :font "JetBrainsMono Nerd Font" :height 130)
(set-face-attribute 'default nil :font "Iosevka Term" :height 130 :width 'expanded) (set-face-attribute 'default nil :font "Iosevka Term SS14" :height 130)
(set-face-attribute 'fixed-pitch nil :font "Iosevka Term" :height 130 :width 'expanded) (set-face-attribute 'fixed-pitch nil :font "Iosevka Term SS14" :height 130)
(set-face-attribute 'variable-pitch nil :font "Iosevka Etoile" :height 130) (set-face-attribute 'variable-pitch nil :font "Iosevka Etoile" :height 130)
#+END_SRC #+END_SRC