1437 lines
44 KiB
Org Mode
1437 lines
44 KiB
Org Mode
* Overall Structure
|
||
|
||
This is the basic structure of the home.nix file. Individual sections are defined later.
|
||
|
||
#+BEGIN_SRC nix :noweb no-export :tangle ~/.config/home-manager/home.nix
|
||
{ config, pkgs, ... }:
|
||
|
||
{
|
||
home.stateVersion = "22.05";
|
||
|
||
<<personal>>
|
||
|
||
home.packages = with pkgs; [
|
||
<<packages>>
|
||
];
|
||
|
||
<<path>>
|
||
|
||
programs = {
|
||
<<programs>>
|
||
};
|
||
|
||
xdg = {
|
||
enable = true;
|
||
<<extra_xdg>>
|
||
};
|
||
}
|
||
#+END_SRC
|
||
|
||
* Personal Info
|
||
|
||
Home manager requires this stuff. Just my name and where my home directory is. At some point, I need to make this more dynamic (perhaps using chezmoi), but for now it's hard-coded.
|
||
|
||
#+NAME: personal
|
||
#+BEGIN_SRC nix
|
||
home.username = "jfrikker";
|
||
home.homeDirectory = "/Users/jfrikker";
|
||
#+END_SRC
|
||
|
||
* Packages
|
||
:PROPERTIES:
|
||
:header-args: :noweb-ref packages
|
||
:END:
|
||
|
||
~SBCL~ is the current leading open-source common lisp compiler. It requires any libraries you want to be availble to be installed using withPackages. I really should install this per-project using direnv, rather than globally. I think it may work today, but I think I want to start using ~SBCL~ for scripting / exploratory development. So for now, it stays global.
|
||
|
||
#+BEGIN_SRC nix
|
||
rlwrap
|
||
roswell
|
||
(sbcl.withPackages (ps: with ps; [
|
||
_3bmd
|
||
_3bmd-ext-code-blocks
|
||
agnostic-lizard
|
||
alexandria
|
||
anypool
|
||
arrows
|
||
async-process
|
||
binding-arrows
|
||
bt-semaphore
|
||
chanl
|
||
cl-annot
|
||
cl-charms
|
||
cl-markup
|
||
cl-migratum
|
||
cl-migratum_dot_provider_dot_local-path
|
||
cl-migratum_dot_driver_dot_dbi
|
||
cl-mock
|
||
cl-punch
|
||
cl-rdkafka
|
||
cl-readline
|
||
cl-setlocale
|
||
clack
|
||
clack-handler-hunchentoot
|
||
clack-handler-woo
|
||
dbd-mysql
|
||
dbi
|
||
deploy
|
||
dexador
|
||
fare-csv
|
||
fiveam
|
||
group-by
|
||
inquisitor
|
||
lack-request
|
||
lack-response
|
||
lisp-preprocessor
|
||
local-time
|
||
log4cl
|
||
mito
|
||
mockingbird
|
||
myway
|
||
prove
|
||
prove-asdf
|
||
queues
|
||
queues_dot_priority-cqueue
|
||
queues_dot_simple-cqueue
|
||
replic
|
||
serapeum
|
||
shasht
|
||
slynk
|
||
smug
|
||
split-sequence
|
||
str
|
||
sxql-composer
|
||
trivial-ws
|
||
trivial-open-browser
|
||
trivial-timeout
|
||
uuid
|
||
yason ]))
|
||
#+END_SRC
|
||
|
||
These are the other programs I have installed globally. A few (like ~awscli~, ~mysql-client~, etc.) are still Shibumi specific; ideally I'd find another way to install them.
|
||
|
||
Chezmoi is what I use to manage this file; it can pull it from GitHub, and handle a few configuration variations. I may be able to replace it with org mode?
|
||
|
||
#+BEGIN_SRC nix
|
||
aws-iam-authenticator
|
||
awscli
|
||
bashInteractive
|
||
chezmoi
|
||
dust
|
||
fd
|
||
fend
|
||
kubectl
|
||
ledger
|
||
magic-wormhole
|
||
neovim
|
||
nil
|
||
openssh
|
||
ripgrep
|
||
tokei
|
||
xh
|
||
yubikey-manager
|
||
#+END_SRC
|
||
|
||
* Program Configurations
|
||
:PROPERTIES:
|
||
:header-args: :noweb-ref programs :noweb no-export
|
||
:END:
|
||
|
||
This section contains applications whose config files will be generated by Home Manager. Home Manager calls these "programs" (as opposed to "packages", which are just binaries to put on the path).
|
||
|
||
** Simple Programs
|
||
|
||
Although Home-Manager generates config files for these programs, they don't need their own dedicated configuration. I'm not sure what benefit there is to enabling ~jq~ as a Home Manager program, rather than just as an available package, but there doesn't seem to be a downside.
|
||
|
||
#+BEGIN_SRC nix
|
||
bash.enable = true;
|
||
gh.enable = true;
|
||
home-manager.enable = true;
|
||
jq.enable = true;
|
||
lazygit.enable = true;
|
||
zoxide.enable = true;
|
||
#+END_SRC
|
||
|
||
** Bat
|
||
|
||
~bat~ is a less alternative that performs syntax highlighting for a variety of languages. It also provides syntax-highlighting versions of a few other commands. It's honestly not incredibly useful, but still nice to have.
|
||
|
||
#+BEGIN_SRC nix
|
||
bat.enable = true;
|
||
bat.config.style = "numbers";
|
||
#+END_SRC
|
||
|
||
** Direnv
|
||
|
||
~direnv~ allows loading per-project paths as I navigate to their directories on the command line. I leverage this with the emacs ~envrc~ package.
|
||
|
||
#+BEGIN_SRC nix
|
||
direnv.enable = true;
|
||
direnv.nix-direnv.enable = true;
|
||
#+END_SRC
|
||
|
||
** Eza
|
||
|
||
~eza~ is an ~ls~ replacement that offers icons, colors, and some easier command-line options.
|
||
|
||
#+BEGIN_SRC nix
|
||
eza.enable = true;
|
||
eza.enableBashIntegration = true;
|
||
eza.enableZshIntegration = true;
|
||
eza.icons = "auto";
|
||
#+END_SRC
|
||
|
||
** Fzf
|
||
|
||
~fzf~ offers a variety of fuzzy finders right from the shell. I haven't been using this, so I'll turn it off for now.
|
||
|
||
#+BEGIN_SRC nix
|
||
fzf.defaultCommand = "fd --type f";
|
||
fzf.fileWidgetCommand = "fd --type f";
|
||
fzf.fileWidgetOptions = ["--preview" "'bat --color=always --style=numbers --line-range=:500 {}'"];
|
||
fzf.changeDirWidgetCommand = "fd --type d";
|
||
fzf.tmux.enableShellIntegration = true;
|
||
#+END_SRC
|
||
|
||
** Git
|
||
|
||
We all know what ~git~ does.
|
||
|
||
#+BEGIN_SRC nix
|
||
git.enable = true;
|
||
git.settings.user.name = "Joe Frikker";
|
||
git.settings.user.email = "joe.frikker@shibumi.com";
|
||
delta.enable = true;
|
||
delta.enableGitIntegration = true;
|
||
#+END_SRC
|
||
|
||
** Helix
|
||
|
||
The best text editor ever? Heresy!
|
||
|
||
#+BEGIN_SRC nix
|
||
helix.enable = true;
|
||
helix.defaultEditor = true;
|
||
|
||
helix.settings.editor = {
|
||
auto-format = false;
|
||
auto-pairs = false;
|
||
auto-save.after-delay.enable = true;
|
||
auto-save.after-delay.timeout = 1000;
|
||
cursorline = true;
|
||
idle-timeout = 0;
|
||
rulers = [100];
|
||
text-width = 100;
|
||
lsp.goto-reference-include-declaration = false;
|
||
cursor-shape.insert = "bar";
|
||
smart-tab.supersede-menu = true;
|
||
whitespace.render.newline = "all";
|
||
};
|
||
|
||
helix.settings.keys.normal.space = {
|
||
space = "file_picker";
|
||
"," = "buffer_picker";
|
||
# b = "@:sh wezterm cli spawn --cwd . -- tig blame <C-r>%<ret>";
|
||
};
|
||
|
||
|
||
helix.languages.language-server.eslint = {
|
||
args = ["--stdio"];
|
||
command = "vscode-eslint-language-server";
|
||
config.nodePath = "";
|
||
config.quiet = false;
|
||
config.rulesCustomizations = [];
|
||
config.run = "onType";
|
||
config.validate = "on";
|
||
config.codeAction.disableRuleComment.enable = true;
|
||
config.codeAction.disableRuleComment.location = "separateLine";
|
||
config.codeAction.showDocumentation.enable = true;
|
||
config.problems.shortenToSingleLine = false;
|
||
};
|
||
|
||
helix.languages.language-server.jdtls.config.java = {
|
||
autobuild.enabled = true;
|
||
completion.maxResults = 1000;
|
||
format.settings.url = "https://raw.githubusercontent.com/google/styleguide/gh-pages/eclipse-java-google-style.xml";
|
||
};
|
||
|
||
helix.languages.language-server.rust-analyzer.config.files.watcher = "client";
|
||
|
||
helix.languages.language = [
|
||
{
|
||
name = "typescript";
|
||
language-servers = [ "typescript-language-server" "vscode-eslint-language-server" ];
|
||
indent.tab-width = 4;
|
||
indent.unit = " ";
|
||
}
|
||
{
|
||
name = "tsx";
|
||
language-servers = [ "typescript-language-server" "vscode-eslint-language-server" ];
|
||
indent.tab-width = 4;
|
||
indent.unit = " ";
|
||
}
|
||
{
|
||
name = "java";
|
||
indent.tab-width = 4;
|
||
indent.unit = " ";
|
||
}
|
||
];
|
||
#+END_SRC
|
||
|
||
** Starship
|
||
|
||
~starship~ gives me a nice shell prompt, mostly showing the versions of relevant software I have installed. It's shell-agnostic, so it works with both bash and zsh.
|
||
|
||
#+BEGIN_SRC nix :noweb no-export
|
||
starship.enable = true;
|
||
starship.settings = {
|
||
add_newline = false;
|
||
container.disabled = true;
|
||
git_branch.symbol = " ";
|
||
git_status.ahead = "⇡\${count}";
|
||
git_status.behind = "⇣\${count}";
|
||
git_status.diverged = "⇕⇡\${ahead_count}⇣\${behind_count}";
|
||
git_status.format = "([\\[\$conflicted\$staged\$ahead_behind\\]](\$style) )";
|
||
java.symbol = " ";
|
||
line_break.disabled = true;
|
||
nix_shell.symbol = " ";
|
||
nodejs.symbol = " ";
|
||
package.disabled = true;
|
||
palette = "catppuccin_frappe";
|
||
python.symbol = " ";
|
||
package.symbol = " ";
|
||
rust.symbol = " ";
|
||
docker_context.disabled = true;
|
||
shell.disabled = false;
|
||
} //
|
||
<<starship_colors>>
|
||
;
|
||
#+END_SRC
|
||
|
||
** Tmux
|
||
|
||
I'm using ~wezterm~ instead of ~tmux~ for now, so this is disabled, but I'm keeping the config here in case I need it later.
|
||
|
||
#+BEGIN_SRC nix
|
||
tmux.baseIndex = 1;
|
||
tmux.clock24 = true;
|
||
tmux.customPaneNavigationAndResize = true;
|
||
tmux.historyLimit = 50000;
|
||
tmux.enable = true;
|
||
tmux.escapeTime = 0;
|
||
tmux.keyMode = "vi";
|
||
tmux.mouse = true;
|
||
tmux.shell = pkgs.zsh + "/bin/zsh";
|
||
tmux.shortcut = "Space";
|
||
tmux.tmuxinator.enable = true;
|
||
tmux.terminal = "xterm-256color";
|
||
tmux.extraConfig = ''
|
||
bind-key -T copy-mode-vi 'v' send -X begin-selection
|
||
bind-key -T copy-mode-vi 'y' send -X copy-selection-and-cancel
|
||
|
||
bind-key -T launcher g popup -h 100% -w 100% -E lazygit
|
||
bind-key g switch-client -Tlauncher
|
||
set -g default-command ""
|
||
'';
|
||
#+END_SRC
|
||
** Wezterm
|
||
|
||
~wezterm~ is a fast terminal emulator and multiplexer. It is configured using lua. We'll define its config in two blocks, so we can get lua syntax highlighting in org. First, the nix configuration:
|
||
|
||
#+BEGIN_SRC nix :noweb no-export
|
||
wezterm.enable = true;
|
||
wezterm.extraConfig = ''
|
||
local config = {}
|
||
<<wezterm_colors>>
|
||
<<wezterm>>
|
||
'';
|
||
#+END_SRC
|
||
|
||
Then the real lua config:
|
||
|
||
#+BEGIN_SRC lua :noweb-ref wezterm
|
||
config.default_prog = { '/Users/jfrikker/.nix-profile/bin/zsh', '-l' }
|
||
config.font_size = 13.0
|
||
-- config.font = wezterm.font("JetBrains Mono")
|
||
config.inactive_pane_hsb = {
|
||
saturation = 0.5,
|
||
brightness = 0.5,
|
||
}
|
||
config.pane_focus_follows_mouse = true
|
||
config.switch_to_last_active_tab_when_closing_tab = true
|
||
config.tab_bar_at_bottom = true
|
||
config.use_fancy_tab_bar = false
|
||
config.window_decorations = "RESIZE"
|
||
#+END_SRC
|
||
|
||
I use a workspace switcher plugin, bouned to ~cmd-s~, that lets me quickly switch between per-project workspaces using a single OS window.
|
||
|
||
#+BEGIN_SRC lua :noweb-ref wezterm
|
||
local workspace_switcher = wezterm.plugin.require("https://github.com/MLFlexer/smart_workspace_switcher.wezterm")
|
||
workspace_switcher.zoxide_path='~/.nix-profile/bin/zoxide'
|
||
#+END_SRC
|
||
|
||
Set up a default window layout when switching to a workspace that hasn't been opened in this session yet. This will create three tabs, caled "edit", "run", and "term", and open helix in the first one. I use "edit" for running the editor (obviously), "run" for building / running the application, and "term" for miscellaneous other tasks. I sometimes split the "run" window into multiple panes if the project requires multiple things to run simultaneously.
|
||
|
||
#+BEGIN_SRC lua :noweb-ref wezterm
|
||
wezterm.on('smart_workspace_switcher.workspace_switcher.created', function(window, path, workspace)
|
||
local editor = window:active_tab()
|
||
editor:set_title("edit")
|
||
editor:panes()[1]:send_text("hx\n")
|
||
local run = window:spawn_tab {}
|
||
run:set_title "run"
|
||
local term = window:spawn_tab {}
|
||
term:set_title "term"
|
||
editor:activate()
|
||
end)
|
||
|
||
#+END_SRC
|
||
|
||
Put the current workspace name in the lower-right corner of the window. Taken from [https://alexplescan.com/posts/2024/08/10/wezterm/].
|
||
|
||
#+BEGIN_SRC lua :noweb-ref wezterm
|
||
local function segments_for_right_status(window)
|
||
return {
|
||
window:active_workspace(),
|
||
}
|
||
end
|
||
|
||
wezterm.on('update-status',
|
||
function(window, _)
|
||
local SOLID_LEFT_ARROW = utf8.char(0xe0b2)
|
||
local segments = segments_for_right_status(window)
|
||
|
||
local color_scheme = window:effective_config().resolved_palette
|
||
-- Note the use of wezterm.color.parse here, this returns
|
||
-- a Color object, which comes with functionality for lightening
|
||
-- or darkening the colour (amongst other things).
|
||
local bg = wezterm.color.parse(color_scheme.background)
|
||
local fg = color_scheme.foreground
|
||
|
||
-- Each powerline segment is going to be coloured progressively
|
||
-- darker/lighter depending on whether we're on a dark/light colour
|
||
-- scheme. Let's establish the "from" and "to" bounds of our gradient.
|
||
local gradient_to, gradient_from = bg
|
||
gradient_from = gradient_to:lighten(0.2)
|
||
|
||
-- Yes, WezTerm supports creating gradients, because why not?! Although
|
||
-- they'd usually be used for setting high fidelity gradients on your terminal's
|
||
-- background, we'll use them here to give us a sample of the powerline segment
|
||
-- colours we need.
|
||
local gradient = wezterm.color.gradient(
|
||
{
|
||
orientation = 'Horizontal',
|
||
colors = { gradient_from, gradient_to },
|
||
},
|
||
#segments -- only gives us as many colours as we have segments.
|
||
)
|
||
|
||
-- We'll build up the elements to send to wezterm.format in this table.
|
||
local elements = {}
|
||
|
||
for i, seg in ipairs(segments) do
|
||
local is_first = i == 1
|
||
|
||
if is_first then
|
||
table.insert(elements, { Background = { Color = 'none' } })
|
||
end
|
||
table.insert(elements, { Foreground = { Color = gradient[i] } })
|
||
table.insert(elements, { Text = SOLID_LEFT_ARROW })
|
||
|
||
table.insert(elements, { Foreground = { Color = fg } })
|
||
table.insert(elements, { Background = { Color = gradient[i] } })
|
||
table.insert(elements, { Text = ' ' .. seg .. ' ' })
|
||
end
|
||
|
||
window:set_right_status(wezterm.format(elements))
|
||
end)
|
||
#+END_SRC
|
||
|
||
Now we'll set up some keybindings:
|
||
|
||
| Key | Action |
|
||
| s-s | Switch Workspace |
|
||
| s-- | Vertical Split |
|
||
| s-\ | Horizontal split |
|
||
| s-hjkl | Switch to the pane in that direction |
|
||
| s-g | Launch ~lazygit~ in a new tab. The tab closes when ~lazygit~ exits. |
|
||
| s-z | Toggle full-screen zoom for the active pane. |
|
||
| s-t | Launch a terminal in a new tab. |
|
||
| s-d | Close the current tab (with confirmation). |
|
||
| s-123456789 | Switch to the tab with the corresponding number. |
|
||
|
||
#+BEGIN_SRC lua :noweb-ref wezterm
|
||
config.leader = { key = ' ', mods = 'CTRL', timeout_milliseconds = 10000 }
|
||
config.keys = {
|
||
{
|
||
key = "s",
|
||
mods = "CMD",
|
||
action = workspace_switcher.switch_workspace(),
|
||
},
|
||
{
|
||
key = "-",
|
||
mods = "CMD",
|
||
action = wezterm.action.SplitVertical {},
|
||
},
|
||
{
|
||
key = "\\",
|
||
mods = "CMD",
|
||
action = wezterm.action.SplitHorizontal {},
|
||
},
|
||
{
|
||
key = "h",
|
||
mods = "CMD",
|
||
action = wezterm.action.ActivatePaneDirection "Left",
|
||
},
|
||
{
|
||
key = "j",
|
||
mods = "CMD",
|
||
action = wezterm.action.ActivatePaneDirection "Down",
|
||
},
|
||
{
|
||
key = "k",
|
||
mods = "CMD",
|
||
action = wezterm.action.ActivatePaneDirection "Up",
|
||
},
|
||
{
|
||
key = "l",
|
||
mods = "CMD",
|
||
action = wezterm.action.ActivatePaneDirection "Right",
|
||
},
|
||
{
|
||
key = "g",
|
||
mods = "CMD",
|
||
action = wezterm.action.SpawnCommandInNewTab {
|
||
args = { wezterm.home_dir .. "/.nix-profile/bin/zsh", "-l", "-c", "lazygit" }
|
||
}
|
||
},
|
||
{
|
||
key = "t",
|
||
mods = "CMD",
|
||
action = wezterm.action.SpawnCommandInNewTab {}
|
||
},
|
||
{
|
||
key = 'z',
|
||
mods = 'CMD',
|
||
action = wezterm.action.TogglePaneZoomState,
|
||
},
|
||
{
|
||
key = 'd',
|
||
mods = 'CMD',
|
||
action = wezterm.action.CloseCurrentTab { confirm = true },
|
||
},
|
||
}
|
||
|
||
for i = 1, 9 do
|
||
-- CTRL+ALT + number to activate that tab
|
||
table.insert(config.keys, {
|
||
key = tostring(i),
|
||
mods = 'LEADER',
|
||
action = wezterm.action.ActivateTab(i - 1),
|
||
})
|
||
end
|
||
|
||
return config
|
||
#+END_SRC
|
||
|
||
** Zsh
|
||
|
||
This is my default shell for now. Unfortunately, nix requires a posix-compliant shell, so bash or zsh it is.
|
||
|
||
#+BEGIN_SRC nix
|
||
zsh.enable = true;
|
||
zsh.oh-my-zsh.enable = true;
|
||
zsh.syntaxHighlighting.enable = true;
|
||
zsh.autosuggestion.enable = true;
|
||
zsh.historySubstringSearch.enable = true;
|
||
zsh.history.share = false;
|
||
zsh.cdpath = ["~/source"];
|
||
#+END_SRC
|
||
|
||
Actually, nix *really* requires ~bash~. This is a plugin that allows using zsh from nix-shell.
|
||
|
||
#+BEGIN_SRC nix
|
||
zsh.plugins = [
|
||
{
|
||
name = "zsh-nix-shell";
|
||
file = "nix-shell.plugin.zsh";
|
||
src = pkgs.fetchFromGitHub {
|
||
owner = "chisui";
|
||
repo = "zsh-nix-shell";
|
||
rev = "v0.7.0";
|
||
sha256 = "149zh2rm59blr2q458a5irkfh82y3dwdich60s9670kl3cl5h2m1";
|
||
};
|
||
}
|
||
];
|
||
#+END_SRC
|
||
|
||
* Emacs
|
||
|
||
Emacs is a huge portion of this configuration, so although it's a home-manager "program", I'm breaking it out into its own top-level section. Many of the sections here have two code blocks: a nix code block listing the emacs packages to include, and an elisp code block to configure them in emacs.
|
||
|
||
#+BEGIN_SRC nix :noweb no-export :noweb-ref programs
|
||
emacs.enable = true;
|
||
emacs.extraPackages = epkgs: with epkgs; [
|
||
<<emacs_packages>>
|
||
];
|
||
emacs.extraConfig = ''
|
||
<<emacs_early>>
|
||
<<emacs_config>>
|
||
'';
|
||
#+END_SRC
|
||
|
||
** Global Settings
|
||
|
||
These are just some general settings that apply everywhere. First, a few packages:
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
doom-modeline
|
||
ligature
|
||
mixed-pitch
|
||
ace-window
|
||
#+END_SRC
|
||
|
||
Turn off some default settings that I don't find useful.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(setq inhibit-startup-screen t)
|
||
(setq initial-scratch-message nil)
|
||
(menu-bar-mode -1)
|
||
(scroll-bar-mode -1)
|
||
(tool-bar-mode -1)
|
||
(setq make-backup-files nil)
|
||
(setq split-window-threshold 200)
|
||
(setq split-height-threshold 200)
|
||
(setq view-read-only t)
|
||
#+END_SRC
|
||
|
||
Make sure which-key mode is always on. The on-the-fly keymap help it gives is indespensable.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(which-key-mode)
|
||
#+END_SRC
|
||
|
||
Automatically refresh ~dired~ buffers when switching to them, instead of requiring an explicit refresh.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(setq dired-auto-revert-buffer t)
|
||
#+END_SRC
|
||
|
||
Similarly, highlighting the line the cursor is on is really useful for figuring out where you are, especially on monitors with a lot of vertical space.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(global-hl-line-mode)
|
||
#+END_SRC
|
||
|
||
From the docs: "If ‘complete’, TAB first tries to indent the current line, and if the line was already indented, then try to complete the thing at point." Recommended by [[https://github.com/minad/corfu][the ~corfu~ readme]].
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(setq tab-always-indent 'complete)
|
||
#+END_SRC
|
||
|
||
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 switched to a block cursor during normal mode, just because I was so used to it from Helix and Vim. Now, I don't think there's really a need to ever switch.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(setq-default cursor-type 'bar)
|
||
#+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 :noweb-ref emacs_config
|
||
(auto-save-visited-mode)
|
||
#+END_SRC
|
||
|
||
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 repeats set up that only apply in that mode.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(repeat-mode)
|
||
#+END_SRC
|
||
|
||
Save the minibuffer history to disk, so recently-used options show up at the top of the picker across restarts.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(savehist-mode)
|
||
#+END_SRC
|
||
|
||
The doom modeline looks nice. I'm turning off irc notifications, because it was slow to update (and it would update after every command, slowing down everything). I don't need the workspace name when I have the tab bar at the top of the window. The other settings just clear up some space, and make things look at little nicer.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(setq doom-modeline-irc nil)
|
||
(setq doom-modeline-workspace-name nil)
|
||
(setq doom-modeline-buffer-encoding nil)
|
||
(setq doom-modeline-vcs-max-length 30)
|
||
(doom-modeline-mode)
|
||
#+END_SRC
|
||
|
||
Ligature mode combines character sequences like <= into a single on-screen glyph. It looks kind of cool, so I'm turning it on in prog mode. The enabled ligatures are font-specific, taken from [[https://github.com/mickeynp/ligature.el/wiki#jetbrains-mono][the ligature wiki]].
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package ligature
|
||
:after prog-mode
|
||
:config
|
||
(ligature-set-ligatures 'prog-mode '("--" "---" "==" "===" "!=" "!==" "=!="
|
||
"=:=" "=/=" "<=" ">=" "&&" "&&&" "&=" "++" "+++" "***" ";;" "!!"
|
||
"??" "???" "?:" "?." "?=" "<:" ":<" ":>" ">:" "<:<" "<>" "<<<" ">>>"
|
||
"<<" ">>" "||" "-|" "_|_" "|-" "||-" "|=" "||=" "##" "###" "####"
|
||
"#{" "#[" "]#" "#(" "#?" "#_" "#_(" "#:" "#!" "#=" "^=" "<$>" "<$"
|
||
"$>" "<+>" "<+" "+>" "<*>" "<*" "*>" "</" "</>" "/>" "<!--" "<#--"
|
||
"-->" "->" "->>" "<<-" "<-" "<=<" "=<<" "<<=" "<==" "<=>" "<==>"
|
||
"==>" "=>" "=>>" ">=>" ">>=" ">>-" ">-" "-<" "-<<" ">->" "<-<" "<-|"
|
||
"<=|" "|=>" "|->" "<->" "<~~" "<~" "<~>" "~~" "~~>" "~>" "~-" "-~"
|
||
"~@" "[||]" "|]" "[|" "|}" "{|" "[<" ">]" "|>" "<|" "||>" "<||"
|
||
"|||>" "<|||" "<|>" "..." ".." ".=" "..<" ".?" "::" ":::" ":=" "::="
|
||
":?" ":?>" "//" "///" "/*" "*/" "/=" "//=" "/==" "@_" "__" "???"
|
||
"<:<" ";;;"))
|
||
(global-ligature-mode t))
|
||
#+END_SRC
|
||
|
||
Use variable-width fonts in text buffers. ~mixed-pitch-mode~ keeps most code blocks as monospace.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(add-hook 'text-mode-hook 'mixed-pitch-mode)
|
||
|
||
(defun no-mixed-pitch ()
|
||
(mixed-pitch-mode -1))
|
||
|
||
(add-hook 'yaml-ts-mode-hook 'no-mixed-pitch)
|
||
(add-hook 'mhtml-mode 'no-mixed-pitch)
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package ace-window
|
||
:bind (("M-o" . ace-window)
|
||
("s-o" . ace-window))
|
||
:config
|
||
(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
|
||
(setq aw-dispatch-always t))
|
||
#+END_SRC
|
||
|
||
Set up a few project- / workspace-related key bindings.
|
||
|
||
| Key | Action |
|
||
| s-f | Open file in current project (C-x p f) |
|
||
| s-F | Switch project (C-x p p) |
|
||
| S-s | Switch tab (C-x t RET) |
|
||
|
||
,#+BEGIN_SRC elisp :noweb no :noweb-ref emacs_config
|
||
(bind-keys ("s-f" . project-find-file)
|
||
("s-F" . project-switch-project))
|
||
(bind-keys :map tab-bar-mode-map
|
||
("s-s" . tab-bar-switch-to-tab))
|
||
#+END_SRC
|
||
|
||
Don't run a server. I'm not using this, I can always turn it back on if I need to.
|
||
|
||
#+BEGIN_SRC elisp :noweb no :noweb-ref emacs_config
|
||
(server-mode -1)
|
||
#+END_SRC
|
||
|
||
All the beeping is annoying. This flashes a huge icon over the screen, which is still annoying, but less so?
|
||
|
||
#+BEGIN_SRC elisp :noweb no :noweb-ref emacs_config
|
||
(setq visible-bell t)
|
||
#+END_SRC
|
||
|
||
I'm trying this out. This disables visual selections. It's bold, which is why I like it :)
|
||
|
||
#+BEGIN_SRC elisp :noweb no :noweb-ref emacs_config
|
||
(transient-mark-mode -1)
|
||
#+END_SRC
|
||
|
||
** Editing
|
||
|
||
This configuration affects general text editing, across all modes. First, some packages:
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
avy
|
||
devil
|
||
edit-indirect
|
||
god-mode
|
||
string-inflection
|
||
#+END_SRC
|
||
|
||
I find Emacs to be almost unusable on a normal keyboard unless there's some way to avoid all the modifier keys. I tried Evil mode first. But although I love Vim, it just seemed to be hiding too much of the Emacs native functionality. The keybindings were also much harder to configure. I tried God mode, which has the benefit of re-using the normal Emacs keybindings and commands. It was annoying, though, because some read-only buffers (like magit buffers) have their own "normal-mode" commands that don't use modifiers. It felt jarring to switch to "insert mode" to use those keys. It's also hard to repeat sequences of M-f, M-b, etc. I could have made a ton of repeat maps, but I'm worried that having too many repeat maps will also be annoying (I'll have to explicitly cancel them more frequently). In the end, I opted for Devil mode. It avoids modifier keys, and has its own devil-mode-only repeat maps that don't interfere when using normal modifier key sequences.
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package devil
|
||
:disable t
|
||
:config
|
||
(global-devil-mode)
|
||
(setq devil-repeatable-keys
|
||
'(("%k /")
|
||
("%k d")
|
||
("%k k")
|
||
("%k m ^")
|
||
("%k m b" "%k m f" "%k m a" "% k m e")
|
||
("%k m @" "%k m h")
|
||
("%k m y")
|
||
("%k p" "%k n" "%k b" "%k f" "%k a" "%k e")
|
||
("%k s")
|
||
("%k m d" "%k m <backspace>"))))
|
||
|
||
(use-package god-mode
|
||
:config
|
||
(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 (if (or god-local-mode buffer-read-only) 'box 'bar)))
|
||
|
||
(add-hook 'post-command-hook #'my-god-mode-update-cursor-type)
|
||
(which-key-enable-god-mode-support))
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package avy
|
||
:bind ("M-j" . avy-goto-char-timer))
|
||
|
||
(defun avy-goto-char-timer-embark ()
|
||
(interactive)
|
||
(require 'avy)
|
||
(require 'embark)
|
||
(let ((avy-action-oneshot
|
||
(lambda (pt)
|
||
(unwind-protect
|
||
(save-excursion
|
||
(goto-char pt)
|
||
(embark-act))
|
||
(select-window
|
||
(cdr (ring-ref avy-ring 0)))))))
|
||
(avy-goto-char-timer)))
|
||
|
||
(bind-keys
|
||
("M-J" . avy-goto-char-timer-embark))
|
||
|
||
(use-package isearch
|
||
:custom
|
||
(isearch-wrap-pause 'no-ding))
|
||
|
||
(use-package string-inflection
|
||
:commands
|
||
string-inflection-java-style-cycle
|
||
string-inflection-rust-style-cycle
|
||
:config
|
||
(defun string-inflection-rust-style-cycle-function (str)
|
||
(cond
|
||
((string-inflection-snake-case-p str)
|
||
(string-inflection-upcase-function str))
|
||
((string-inflection-upcase-p str)
|
||
(string-inflection-pascal-case-function str))
|
||
(t
|
||
(string-inflection-snake-case-function str))))
|
||
(defun string-inflection-rust-style-cycle ()
|
||
(interactive)
|
||
(string-inflection--symbol-or-region #'string-inflection-rust-style-cycle-function))
|
||
(defvar-keymap string-inflection-java-map
|
||
:repeat t
|
||
"u" #'string-inflection-java-style-cycle)
|
||
(defvar-keymap string-inflection-rust-map
|
||
:repeat t
|
||
"u" #'string-inflection-rust-style-cycle))
|
||
|
||
(use-package edit-indirect
|
||
:bind ("C-x 4 n" . edit-indirect-region))
|
||
#+END_SRC
|
||
|
||
** Language Support
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
consult-eglot
|
||
haskell-ts-mode
|
||
jenkinsfile-mode
|
||
lispy
|
||
lua-mode
|
||
nix-mode
|
||
rust-mode
|
||
smartparens
|
||
sly
|
||
sly-macrostep
|
||
sql-indent
|
||
tree-sitter
|
||
treesit-grammars.with-all-grammars
|
||
yaml-pro
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package nix-mode
|
||
:mode "\\.nix\\'")
|
||
|
||
(use-package nix-flake
|
||
:bind ("C-x p n" . project-nix-flake)
|
||
:config
|
||
(defun project-nix-flake ()
|
||
(interactive)
|
||
(nix-flake (project-root (project-current t)))))
|
||
|
||
(use-package lua-mode
|
||
:mode "\\.lua\\'")
|
||
|
||
(use-package jenkinsfile-mode
|
||
:mode "\\.jenkinsfile\\'")
|
||
|
||
(setq major-mode-remap-alist '((rust-mode . rust-mode)))
|
||
|
||
(use-package rust-mode
|
||
:init (setq rust-mode-treesitter-derive t))
|
||
|
||
(defun yaml-validate ()
|
||
(interactive)
|
||
(compile (concat "yamllint -d '{extends: default, rules: {indentation: {indent-sequences: false}, braces: {max-spaces-inside: 1}}}' " (buffer-file-name)) t))
|
||
|
||
(use-package yaml-ts-mode
|
||
:mode "\\.yaml\\'")
|
||
|
||
(use-package yaml-pro
|
||
:hook (yaml-ts-mode . yaml-pro-ts-mode))
|
||
|
||
(use-package sly
|
||
:hook lisp-mode-hook
|
||
:custom
|
||
(inferior-lisp-program "sbcl"))
|
||
|
||
(use-package sly-macrostep
|
||
:defer t
|
||
:after sly
|
||
:init
|
||
(add-to-list 'sly-contribs 'sly-macrostep))
|
||
|
||
(use-package consult-eglot
|
||
:commands
|
||
consult-eglot-symbols)
|
||
|
||
(use-package typescript-ts-mode
|
||
:mode "\\.ts\\'" ("\\.tsx\\'" . tsx-ts-mode)
|
||
:custom
|
||
(typescript-ts-mode-indent-offset 4)
|
||
(defun tsx-ts-mode--indent-compatibility-b893426 ()
|
||
"Indent rules helper, to handle different releases of tree-sitter-tsx.
|
||
Check if a node type is available, then return the right indent rules."
|
||
;; handle https://github.com/tree-sitter/tree-sitter-typescript/commit/b893426b82492e59388a326b824a346d829487e8
|
||
(condition-case nil
|
||
(progn (treesit-query-capture 'tsx '((jsx_fragment) @capture))
|
||
`(((match "<" "jsx_fragment") parent 0)
|
||
((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset)))
|
||
(treesit-query-error
|
||
`(((match "<" "jsx_text") parent 0)
|
||
((parent-is "jsx_text") grand-parent typescript-ts-mode-indent-offset))))))
|
||
|
||
(use-package rust-ts-mode
|
||
:mode "\\.rs\\'"
|
||
:config
|
||
(bind-keys :map rust-ts-mode-map
|
||
("C-c u" . string-inflection-rust-style-cycle)))
|
||
|
||
(use-package java-ts-mode
|
||
:mode "\\.java\\'"
|
||
:config
|
||
(bind-keys :map java-ts-mode-map
|
||
("C-c u" . string-inflection-java-style-cycle)))
|
||
|
||
(use-package sql-indent
|
||
:hook (sql-mode-hook . sqlind-minor-mode))
|
||
|
||
(use-package haskell-ts-mode
|
||
:mode "\\.hs\\'"
|
||
:custom (haskell-ts-use-indent tc))
|
||
|
||
(use-package flymake
|
||
:bind
|
||
(:map prog-mode-map
|
||
("C-c D" . flymake-show-project-diagnostics)
|
||
("M-n" . flymake-goto-next-error)
|
||
("M-p" . flymake-goto-prev-error)))
|
||
|
||
(use-package eglot
|
||
:commands eglot
|
||
:custom
|
||
(eglot-ignored-server-capabilities '(:inlayHintProvider))
|
||
:config
|
||
(bind-keys :map eglot-mode-map
|
||
("C-c A" . eglot-code-actions)
|
||
("C-c R" . eglot-rename)
|
||
("C-c I" . eglot-find-implementation))
|
||
|
||
(add-hook 'eglot-managed-mode-hook (lambda () (eglot-inlay-hints-mode -1)) nil t))
|
||
|
||
(use-package lispy
|
||
:hook (emacs-lisp-mode lisp-mode)
|
||
:init (setq lispy-compat '(god-mode edebug))
|
||
:config
|
||
(bind-keys :map lispy-mode-map
|
||
("i" . (lambda ()
|
||
(interactive)
|
||
(if god-global-mode
|
||
(god-mode-all -1)
|
||
(special-lispy-tab))))))
|
||
|
||
(use-package smartparens
|
||
:hook
|
||
emacs-lisp-mode
|
||
common-lisp-mode
|
||
:config
|
||
(add-to-list 'sp-lisp-modes 'sly-mrepl-mode)
|
||
(require 'smartparens-config)
|
||
(setq sp-highlight-pair-overlay nil
|
||
sp-highlight-wrap-overlay nil
|
||
sp-highlight-wrap-tag-overlay nil))
|
||
|
||
(setq-default indent-tabs-mode nil)
|
||
(setq-default tab-width 4)
|
||
(global-tree-sitter-mode 1)
|
||
(setq-default fill-column 100)
|
||
(defun jf-init-fill-column ()
|
||
(display-fill-column-indicator-mode 1))
|
||
|
||
(defvar jf/class-name-to-file-search-path (list "src/main/java" "src/test/java"))
|
||
|
||
(defun jf/class-name-to-file (class-name)
|
||
(let ((root (project-root (project-current t)))
|
||
(fragment (format "%s.java" (replace-regexp-in-string "\\." "/" class-name)))
|
||
(result))
|
||
(dolist (p jf/class-name-to-file-search-path result)
|
||
(unless result
|
||
(let ((path (format "%s/%s" p fragment)))
|
||
(when (file-exists-p (concat root path))
|
||
(setq result path)))))))
|
||
|
||
(defun jf/compile-class-to-file ()
|
||
(jf/class-name-to-file (concat (match-string 1) (match-string 2))))
|
||
|
||
;(add-to-list 'compilation-error-regexp-alist-alist
|
||
; '(java-stack-trace .
|
||
; ("^[[:space:]]*at \\(\\(?:[[:lower:]]+\\.\\)+\\)[^(]+(\\([[:alnum:]]+\\)\\.java:\\([[:digit:]]+\\))"
|
||
; jf/compile-class-to-file 3)))
|
||
;(add-to-list 'compilation-error-regexp-alist 'java-stack-trace)
|
||
|
||
(add-hook 'prog-mode-hook 'jf-init-fill-column)
|
||
(add-hook 'java-mode-hook (lambda () (c-set-offset 'arglist-intro '+)))
|
||
|
||
(dolist (hook
|
||
(list 'grep-mode-hook
|
||
'flymake-project-diagnostics-mode-hook
|
||
'xref--xref-buffer-mode-hook
|
||
'embark-collect-mode-hook
|
||
'compilation-mode-hook
|
||
'sly-mrepl-mode-hook
|
||
'eglot-list-connections-mode-hook))
|
||
(add-hook hook 'tab-line-mode))
|
||
|
||
(let ((bottom-window-params '((side . bottom)
|
||
(slot . 1)
|
||
(window-height . 0.33)
|
||
(window-parameters (no-delete-other-windows . t))))
|
||
(right-window-params '((side . right)
|
||
(window-width . 0.5)
|
||
(window-parameters (no-delete-other-windows . t)))))
|
||
(setopt display-buffer-alist
|
||
(mapcar (lambda (buffer) `(,buffer
|
||
(display-buffer-reuse-window display-buffer-in-side-window)
|
||
,@bottom-window-params))
|
||
(list
|
||
"\\*Flymake diagnostics *"
|
||
"\\*Embark Export *"
|
||
"\\*Embark Collect *"
|
||
"\\*xref*"
|
||
"\\*compilation\\*"
|
||
"\\*sly-mrepl *"
|
||
"\\*Messages\\*"
|
||
"\\*EGLOT connections\\*"))))
|
||
|
||
(setq ediff-split-window-function 'split-window-horizontally)
|
||
#+END_SRC
|
||
|
||
** Envrc
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
envrc
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package envrc
|
||
:hook (after-init . envrc-global-mode)
|
||
:custom
|
||
(envrc-show-summary-in-minibuffer nil))
|
||
#+END_SRC
|
||
|
||
** Magit
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
consult-gh
|
||
diff-hl
|
||
forge
|
||
magit
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package magit
|
||
:bind (("C-x g" . magit-status)
|
||
("s-g" . magit-status)
|
||
("C-x M-g" . magit-dispatch)
|
||
("C-c M-g" . magit-file-dispatch))
|
||
:custom
|
||
(magit-save-repository-buffers 'dontask)
|
||
:config
|
||
(set-face-attribute 'git-commit-summary nil :inherit nil)
|
||
(defun magit-fetch-all-on-load ()
|
||
(magit-run-git-async "fetch" "--all"))
|
||
(add-hook 'magit-status-mode-hook 'magit-fetch-all-on-load)
|
||
(remove-hook 'magit-status-headers-hook 'magit-insert-tags-header))
|
||
|
||
(use-package forge
|
||
:after magit)
|
||
|
||
(use-package diff-hl
|
||
:after magit
|
||
:config
|
||
(global-diff-hl-mode)
|
||
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
|
||
#+END_SRC
|
||
|
||
** Vertico
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
cape
|
||
consult
|
||
corfu
|
||
embark
|
||
embark-consult
|
||
marginalia
|
||
orderless
|
||
vertico
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package consult
|
||
:bind (
|
||
("C-c M-x" . consult-mode-command)
|
||
("C-c h" . consult-history)
|
||
("C-c k" . consult-kmacro)
|
||
("C-c m" . consult-man)
|
||
([remap Info-search] . consult-info)
|
||
|
||
("C-x M-:" . consult-complex-command)
|
||
("C-x b" . consult-buffer)
|
||
("s-b" . consult-buffer)
|
||
("C-x 4 b" . consult-buffer-other-window)
|
||
("C-x 5 b" . consult-buffer-other-frame)
|
||
("C-x t b" . consult-buffer-other-tab)
|
||
("C-x r b" . consult-bookmark)
|
||
("C-x p b" . consult-project-buffer)
|
||
|
||
("M-#" . consult-register-load)
|
||
("M-'" . consult-register-store)
|
||
("C-M-#" . consult-register)
|
||
("M-y" . consult-yank-pop)
|
||
("M-g e" . consult-compile-error)
|
||
("M-g f" . consult-flymake)
|
||
("M-g g" . consult-goto-line)
|
||
("M-g M-g" . consult-goto-line)
|
||
("M-g o" . consult-outline)
|
||
("M-g m" . consult-mark)
|
||
("M-g k" . consult-global-mark)
|
||
("M-g i" . consult-imenu)
|
||
("M-g I" . consult-imenu-multi)
|
||
("M-s r" . consult-ripgrep)
|
||
("M-s l" . consult-line)
|
||
("M-s L" . consult-line-multi)
|
||
("M-s e" . consult-isearch-history)
|
||
:map isearch-mode-map
|
||
("M-e" . consult-isearch-history)
|
||
("M-s e" . consult-isearch-history)
|
||
("M-s l" . consult-line)
|
||
("M-s L" . consult-line-multi)
|
||
:map minibuffer-local-map
|
||
("M-s" . consult-history)
|
||
("M-r" . consult-history))
|
||
:hook (completion-list-mode . consult-preview-at-point-mode)
|
||
:init
|
||
(advice-add #'register-preview :override #'consult-register-window)
|
||
(setq register-preview-delay 0.5)
|
||
|
||
;; (setq xref-show-xrefs-function #'consult-xref
|
||
;; xref-show-definitions-function #'consult-xref)
|
||
|
||
:config
|
||
|
||
(consult-customize
|
||
consult-theme :preview-key '(:debounce 0.2 any)
|
||
consult-ripgrep consult-git-grep consult-grep consult-man
|
||
consult-bookmark consult-recent-file consult-xref
|
||
consult--source-bookmark consult--source-file-register
|
||
consult--source-recent-file consult--source-project-recent-file
|
||
;; :preview-key "M-."
|
||
:preview-key '(:debounce 0.4 any))
|
||
|
||
(setq consult-narrow-key "<") ;; "C-+"
|
||
|
||
)
|
||
|
||
(use-package vertico
|
||
:custom
|
||
(vertico-count 25)
|
||
:config
|
||
(vertico-mode))
|
||
|
||
;; (use-package vertico-buffer
|
||
;; :after vertico
|
||
;; :config
|
||
;; (vertico-buffer-mode))
|
||
|
||
(use-package orderless
|
||
:custom
|
||
(completion-styles '(orderless))
|
||
(orderless-matching-styles '(orderless-literal orderless-flex)))
|
||
|
||
(use-package marginalia
|
||
:config
|
||
(marginalia-mode))
|
||
|
||
(use-package embark
|
||
:bind
|
||
(("C-." . embark-act) ;; pick some comfortable binding
|
||
))
|
||
|
||
(use-package corfu
|
||
:custom
|
||
(corfu-cycle t)
|
||
(corfu-popupinfo-mode)
|
||
(corfu-quit-at-boundary nil)
|
||
(corfu-on-exact-match 'show)
|
||
:config
|
||
(global-corfu-mode))
|
||
|
||
;; Consult users will also want the embark-consult package.
|
||
(use-package embark-consult
|
||
:hook (embark-collect-mode . consult-preview-at-point-mode))
|
||
|
||
(use-package cape
|
||
:config
|
||
(add-hook 'completion-at-point-functions #'cape-file))
|
||
#+END_SRC
|
||
|
||
** Org
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
org-bullets
|
||
verb
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package org
|
||
:mode ("\\.org\\'" . org-mode)
|
||
:bind (("C-c a" . org-agenda)
|
||
("C-c c" . org-capture)
|
||
("C-c l" . org-store-link))
|
||
:config
|
||
(add-hook 'org-mode-hook 'visual-line-mode)
|
||
(setq org-todo-keywords
|
||
'((sequence
|
||
"TODO(o)"
|
||
"IN_PROGRESS(p!)"
|
||
"WAITING(w@)"
|
||
"|"
|
||
"DONE(d!)"
|
||
"CANCELLED(c@)"))
|
||
org-capture-templates
|
||
'(("i" "Inbox entry" entry
|
||
(file+headline "~/org/todo.org" "Inbox")
|
||
"** %?\n- Filed %U\n"
|
||
:prepend t)
|
||
("t" "Todo" entry
|
||
(here)
|
||
"** TODO %?\n- State \"TODO\" %U\n")
|
||
("w" "Work stuff")
|
||
("wp" "Work Project" entry
|
||
(file+headline "~/org/todo.org" "Work Projects")
|
||
"*** %?\n"
|
||
:jump-to-captured t)
|
||
("wa" "Work Next Action" entry
|
||
(file+headline "~/org/todo.org" "Work Next Actions")
|
||
"*** TODO %?\n- State \"TODO\" %U\n")
|
||
("p" "Personal stuff")
|
||
("pp" "Personal Project" entry
|
||
(file+headline "~/org/todo.org" "Personal Projects")
|
||
"*** %?\n"
|
||
:jump-to-captured t)
|
||
("pa" "Personal Next Action" entry
|
||
(file+headline "~/org/todo.org" "Personal Next Actions")
|
||
"*** TODO %?\n- State \"TODO\" %U\n"))
|
||
org-agenda-files '("~/org/todo.org")
|
||
org-agenda-todo-ignore-scheduled 'future
|
||
org-agenda-todo-ignore-with-date t
|
||
org-agenda-tags-todo-honor-ignore-options t))
|
||
|
||
(use-package org-bullets
|
||
:hook org-mode-hook)
|
||
|
||
(use-package verb
|
||
:after org
|
||
:bind-keymap
|
||
(:map org-mode-map
|
||
("C-c C-r" . verb-command-map)))
|
||
#+END_SRC
|
||
|
||
** Terminal
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
eshell-vterm
|
||
vterm
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package em-term
|
||
:config
|
||
(push "hx" eshell-visual-commands))
|
||
|
||
(use-package vterm
|
||
:commands vterm)
|
||
|
||
(use-package eshell-vterm
|
||
:after eshell
|
||
:config
|
||
(eshell-vterm-mode))
|
||
#+END_SRC
|
||
|
||
** Slack
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
slack
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package lui
|
||
:defer t
|
||
:custom
|
||
(lui-time-stamp-format "[%Y-%m-%d %H:%M]"))
|
||
|
||
(use-package slack
|
||
:commands
|
||
slack-start
|
||
:custom
|
||
(slack-render-profile-images-p nil)
|
||
(slack-buffer-function #'switch-to-buffer()))
|
||
#+END_SRC
|
||
|
||
** Kubernetes
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
kubed
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref emacs_config
|
||
(use-package kubed
|
||
:bind-keymap
|
||
("s-k" . kubed-prefix-map))
|
||
#+END_SRC
|
||
|
||
** Ledger
|
||
|
||
#+BEGIN_SRC nix :noweb-ref emacs_packages
|
||
ledger-mode
|
||
#+END_SRC
|
||
|
||
* Theme
|
||
|
||
I like Catppuccin Frappe as my theme. Let's use it in as many places as we can.
|
||
|
||
** Bat
|
||
|
||
#+BEGIN_SRC nix :noweb-ref programs
|
||
bat.config.theme = "catppuccin-frappe";
|
||
bat.themes = {
|
||
catppuccin-frappe = {
|
||
src = pkgs.fetchFromGitHub {
|
||
owner = "catppuccin";
|
||
repo = "sublime-text"; # Bat uses sublime syntax for its themes
|
||
rev = "3d8625d937d89869476e94bc100192aa220ce44a";
|
||
sha256 = "3ABUsfJpb6RO6AiuuSL5gwDofJIwC5tlEMzBrlY9/s0=";
|
||
};
|
||
file = "Frappe.tmTheme";
|
||
};
|
||
};
|
||
#+END_SRC
|
||
|
||
** Helix
|
||
|
||
#+BEGIN_SRC nix :noweb-ref programs
|
||
helix.settings.theme = "catppuccin_frappe";
|
||
#+END_SRC
|
||
|
||
** Tmux
|
||
|
||
#+BEGIN_SRC nix :noweb-ref programs
|
||
tmux.plugins = [
|
||
{
|
||
plugin = pkgs.tmuxPlugins.catppuccin;
|
||
extraConfig = ''set -g @catppuccin_window_tabs_enabled on
|
||
set -g @catppuccin_window_default_text "#W"
|
||
set -g @catppuccin_window_current_text "#W"'';
|
||
}
|
||
];
|
||
#+END_SRC
|
||
|
||
** Lazygit
|
||
|
||
#+BEGIN_SRC nix :noweb-ref extra_xdg
|
||
configFile."lazygit/config.yml" = {
|
||
enable = true;
|
||
source = pkgs.fetchFromGitHub
|
||
{
|
||
owner = "catppuccin";
|
||
repo = "lazygit";
|
||
rev = "b2ecb6d41b6f54a82104879573c538e8bdaeb0bf"; # Replace with the latest commit hash
|
||
sha256 = "9BBmWRcjNaJE9T0RKVEJaSnkrbMom0CLYE8PzAT6yFw=";
|
||
} + /themes/frappe.yml;
|
||
};
|
||
#+END_SRC
|
||
|
||
** Starship
|
||
|
||
#+NAME: starship_colors
|
||
#+BEGIN_SRC nix
|
||
builtins.fromTOML (builtins.readFile
|
||
(pkgs.fetchFromGitHub
|
||
{
|
||
owner = "catppuccin";
|
||
repo = "starship";
|
||
rev = "3e3e54410c3189053f4da7a7043261361a1ed1bc"; # Replace with the latest commit hash
|
||
sha256 = "soEBVlq3ULeiZFAdQYMRFuswIIhI9bclIU8WXjxd7oY=";
|
||
} + /palettes/frappe.toml))
|
||
#+END_SRC
|
||
|
||
** Wezterm
|
||
|
||
#+NAME: wezterm_colors
|
||
#+BEGIN_SRC lua
|
||
config.color_scheme = 'Catppuccin Frappe'
|
||
#+END_SRC
|
||
|
||
** Emacs
|
||
|
||
#+BEGIN_SRC nix :noweb-ref "emacs_packages"
|
||
catppuccin-theme
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp :noweb-ref "emacs_config"
|
||
(use-package catppuccin-theme
|
||
:custom
|
||
(catppuccin-flavor 'frappe)
|
||
:config
|
||
(load-theme 'catppuccin :no-confirm))
|
||
|
||
(set-face-attribute 'default nil :font "JetBrainsMono Nerd Font" :height 130)
|
||
(set-face-attribute 'fixed-pitch nil :font "JetBrainsMono Nerd Font" :height 130)
|
||
#+END_SRC
|
||
|
||
* Extra Paths
|
||
|
||
I use cargo install to add personal rust tools to the path, so we need this:
|
||
|
||
#+NAME: path
|
||
#+BEGIN_SRC nix
|
||
home.sessionPath = [
|
||
"$HOME/.cargo/bin"
|
||
];
|
||
#+END_SRC
|