This repository has no description
11 kB
364 lines
1{ inputs, ... }:
2{
3 perSystem =
4 { system, pkgs, ... }:
5 {
6 packages.nvim = inputs.nixvim.legacyPackages.${system}.makeNixvim {
7 vimAlias = true;
8 colorschemes = {
9 ayu = {
10 enable = true;
11 settings = {
12 mirage = false;
13 dark = true;
14 };
15 settings.overrides = {
16 EoLSpace = {
17 bg = "#883333";
18 };
19 };
20 };
21 everforest = {
22 enable = true;
23 settings.overrides = {
24 EoLSpace = {
25 bg = "#FF2222"; # doesn't work
26 };
27 };
28 };
29 };
30 extraConfigLua = ''
31 -- Cross-platform background detection and colorscheme switching
32 local last_theme = nil
33
34 local function detect_and_set_theme()
35 local is_dark = false
36
37 if vim.fn.has("mac") == 1 then
38 -- macOS: check system appearance
39 local result = vim.fn.system("defaults read -g AppleInterfaceStyle 2>/dev/null")
40 is_dark = result:match("Dark") ~= nil
41 elseif vim.fn.has("unix") == 1 then
42 -- Linux: check if running under a dark theme
43 -- Check NixOS theme system first (always check this fresh)
44 local f = io.open("/var/theme/current_theme", "r")
45 if f then
46 local content = f:read("*all"):gsub("^%s+", ""):gsub("%s+$", "")
47 f:close()
48 is_dark = (content == "dark")
49 else
50 -- Fallback to other methods if theme file doesn't exist
51 local methods = {
52 -- GNOME/GTK
53 "gsettings get org.gnome.desktop.interface gtk-theme 2>/dev/null",
54 "gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null",
55 -- KDE
56 "kreadconfig5 --file kdeglobals --group General --key ColorScheme 2>/dev/null",
57 -- Check if COLORFGBG suggests dark background
58 function()
59 local colorfgbg = vim.env.COLORFGBG
60 if colorfgbg then
61 local fg, bg = colorfgbg:match("(%d+);(%d+)")
62 if fg and bg then
63 -- If foreground is lighter than background, likely dark theme
64 return tonumber(fg) > tonumber(bg)
65 end
66 end
67 return false
68 end
69 }
70
71 for _, method in ipairs(methods) do
72 if type(method) == "function" then
73 is_dark = method()
74 if is_dark then break end
75 else
76 local result = vim.fn.system(method)
77 if result:match("[Dd]ark") or result:match("prefer%-dark") then
78 is_dark = true
79 break
80 end
81 end
82 end
83 end
84 end
85
86 local new_theme = is_dark and "dark" or "light"
87
88 if new_theme ~= last_theme then
89 last_theme = new_theme
90 vim.o.background = new_theme
91
92 if is_dark then
93 vim.cmd("colorscheme ayu")
94 else
95 vim.cmd("colorscheme everforest")
96 end
97 end
98 end
99
100 -- Set initial theme
101 vim.defer_fn(detect_and_set_theme, 100)
102
103 -- Check for theme changes every 3 seconds (less frequent to be less resource intensive)
104 local timer = vim.loop.new_timer()
105 timer:start(3000, 3000, vim.schedule_wrap(detect_and_set_theme))
106
107 -- Create a command to manually refresh theme
108 vim.api.nvim_create_user_command("RefreshTheme", detect_and_set_theme, {})
109 '';
110 globals = {
111 mapleader = " ";
112 };
113 opts = {
114 mouse = "a";
115 number = true;
116 shiftwidth = 2;
117 clipboard = "unnamedplus";
118 # undo stuff
119 undofile = true;
120 undolevels = 10000;
121 undoreload = 10000;
122 listchars = "tab:⇥ ,extends:❯,precedes:❮,nbsp:␣,trail:·,eol:↲";
123 };
124 extraConfigVim = ''
125 set et
126
127 " show special characters
128 set list
129
130 " match trailing whitespace
131 match EoLSpace /\s\+$/
132
133 " need to use lua to expand $HOME
134 lua vim.o.undodir = vim.fs.normalize('$HOME/.vim/undodir')
135 '';
136 extraPlugins = [
137 pkgs.vimPlugins.vim-fetch
138 ];
139 keymaps = [
140 {
141 mode = "i";
142 key = "<C-p>";
143 action = "<Nop>";
144 }
145 {
146 mode = "i";
147 key = "<C-n>";
148 action = "<Nop>";
149 }
150 {
151 mode = "n";
152 key = "<C-c>";
153 action = ":q<cr>";
154 }
155 {
156 mode = "n";
157 key = "<Space>";
158 action = "<Nop>";
159 }
160 {
161 mode = [
162 "n"
163 "v"
164 ];
165 key = "<leader>cc";
166 action = ":CopilotChatOpen<cr>";
167 }
168 {
169 mode = [
170 "n"
171 "v"
172 ];
173 key = "<leader>ce";
174 action = ":CopilotChatExplain<cr>";
175 }
176 {
177 mode = [
178 "n"
179 "v"
180 ];
181 key = "<leader>cr";
182 action = ":CopilotChatReview<cr>";
183 }
184 {
185 mode = [
186 "n"
187 "v"
188 ];
189 key = "<leader>cf";
190 action = ":CopilotChatFix<cr>";
191 }
192 {
193 mode = [
194 "n"
195 "v"
196 ];
197 key = "<leader>cd";
198 action = ":CopilotChatDocs<cr>";
199 }
200 {
201 mode = [
202 "n"
203 "x"
204 ];
205 key = "p";
206 action = "<Plug>(YankyPutAfter)";
207 }
208 {
209 mode = [
210 "n"
211 "x"
212 ];
213 key = "P";
214 action = "<Plug>(YankyPutBefore)";
215 }
216 {
217 mode = [
218 "c"
219 "i"
220 "n"
221 "x"
222 ];
223 key = "<M-CR>";
224 action = ":lua vim.lsp.buf.code_action()<CR>";
225 }
226 {
227 mode = [
228 "n"
229 ];
230 key = "gd";
231 action = ":lua vim.lsp.buf.definition()<CR>";
232 }
233 {
234 mode = [
235 "n"
236 ];
237 key = "gD";
238 action = ":lua vim.lsp.buf.declaration()<CR>";
239 }
240 ];
241 # autoCmd = [
242 # {
243 # event = "BufWritePost";
244 # desc = "run treefmt on save";
245 # # https://stackoverflow.com/questions/77466697/how-to-automatically-format-on-save
246 # callback.__raw = ''
247 # function()
248 # vim.cmd("silent !treefmt %")
249 # vim.cmd("edit")
250 # end
251 # '';
252 # }
253 # ];
254 plugins.none-ls = {
255 enable = true;
256 # sources.formatting.treefmt = {
257 # enable = true;
258 # package = pkgs.emptyDirectory;
259 # };
260 # package = pkgs.vimPlugins.none-ls-nvim.overrideAttrs (_old: {
261 # src = pkgs.fetchFromGitHub {
262 # owner = "lassulus";
263 # repo = "none-ls.nvim";
264 # rev = "292c2b5eadea0a097b9a01804aea70f5c8125200";
265 # sha256 = "sha256-nbzqXsxmYfxngdJH3NXMLmGgygh6reSEnruoc6l8t/s=";
266 # };
267 # });
268 sources.formatting.nix_flake_fmt.enable = true;
269 };
270 plugins.web-devicons.enable = true;
271 plugins.telescope.extensions.undo.enable = true;
272 plugins.telescope = {
273 enable = true;
274 keymaps = {
275 "<leader>b" = "buffers";
276 "<leader>u" = "undo";
277 "<leader>ff" = "find_files";
278 "<leader>fg" = "live_grep";
279 "<leader>fh" = "help_tags";
280 "<leader>fp" = "yank_history";
281 };
282 };
283 plugins.lsp-format.enable = true;
284 plugins.lsp-lines.enable = true;
285 plugins.lsp = {
286 enable = true;
287 servers = {
288 bashls.enable = true; # bash
289 nixd = {
290 enable = true; # nix
291 extraOptions.offset_encoding = "utf-8"; # workaround https://github.com/nix-community/nixvim/issues/2390#issuecomment-2408101568
292 };
293 ruff.enable = true; # python
294 pyright.enable = true; # python
295 jsonls.enable = true; # json
296 };
297 };
298 plugins.treesitter.enable = true;
299 plugins.copilot-cmp.enable = true;
300 plugins.copilot-lua.settings.panel.enabled = false;
301 plugins.copilot-lua.settings.suggestion.enabled = false;
302 plugins.cmp_yanky.enable = true;
303 plugins.cmp = {
304 enable = true;
305 autoEnableSources = true;
306 settings = {
307 experimental = {
308 ghost_text = true;
309 };
310 sources = [
311 { name = "nvim_lsp"; }
312 { name = "emoji"; }
313 {
314 name = "buffer"; # text within current buffer
315 option.get_bufnrs.__raw = "vim.api.nvim_list_bufs";
316 keywordLength = 2;
317 }
318 {
319 name = "copilot"; # enable copilot
320 }
321 {
322 name = "path"; # file system paths
323 keywordLength = 3;
324 }
325 { name = "cmp_yanky"; }
326 ];
327
328 mapping = {
329 "<Tab>" = "cmp.mapping.select_next_item()";
330 "<S-Tab>" = "cmp.mapping.select_prev_item()";
331 "<C-n>" = "cmp.mapping.select_next_item()";
332 "<C-p>" = "cmp.mapping.select_prev_item()";
333 "<C-e>" = "cmp.mapping.abort()";
334 "<C-b>" = "cmp.mapping.scroll_docs(-4)";
335 "<C-f>" = "cmp.mapping.scroll_docs(4)";
336 "<CR>" = ''
337 cmp.mapping({
338 i = function(fallback)
339 if cmp.visible() and cmp.get_active_entry() then
340 cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false })
341 else
342 fallback()
343 end
344 end,
345 s = cmp.mapping.confirm({ select = true }),
346 c = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true }),
347 })
348 '';
349 };
350 };
351 };
352 plugins.bufferline.enable = true;
353 plugins.which-key.enable = true;
354 plugins.yanky = {
355 enable = true;
356 enableTelescope = true;
357 };
358 plugins.comment.enable = true;
359 plugins.copilot-chat.enable = true;
360 plugins.undotree.enable = true; # seems to be needed for undo history in telescope
361 plugins.gitsigns.enable = true;
362 };
363 };
364}