change to ghostty

This commit is contained in:
Ray Andrew 2025-11-20 00:40:44 -06:00
parent a64612c293
commit d276de37c8
Signed by: rayandrew
SSH key fingerprint: SHA256:XYrYrxF0Z3A72n8P/p6mqPRNQZT22F88XcLsG+kX4xw
6 changed files with 268 additions and 186 deletions

View file

@ -1,74 +0,0 @@
{
config,
pkgs,
inputs,
lib,
system-font,
...
}:
{
options.custom.gui = with lib; {
ghostty = {
enable = mkEnableOption "Enable ghostty";
};
};
config = lib.mkIf config.custom.gui.ghostty.enable {
home.packages = lib.mkIf pkgs.stdenv.isLinux (
with pkgs;
[
inputs.ghostty.packages."${system}".default
]
);
xdg.configFile."ghostty/config".text = ''
gtk-single-instance = true
gtk-titlebar = false
window-decoration = server
quit-after-last-window-closed = true
# gtk-adwaita = false
font-family = ${system-font}
# font-family = Consolas
font-size = 11
app-notifications = no-clipboard-copy
macos-option-as-alt = left
# theme = gruber-darker
# theme = xcodelighthc
# theme = zenburned
# font-family = Iosevka Nerd Font Mono
# font-size = 13
# background = #062329
background = #072626
# foreground = #d1b897
foreground = #d3b58d
cursor-color = #ffffff
# cursor-text = #d1b897
cursor-text = #d3b58d
# selection-background = #0000ff
# selection-foreground = #d1b897
selection-background = #0000ff
selection-foreground = #d3b58d
# palette = 0=#062329
palette = 0=#072626
# palette = 1=#0b3335
# palette = 2=#0000ff
palette = 3=#44b340
palette = 4=#8cde94
# palette = 5=#d1b897
palette = 5=#d3b58d
palette = 6=#c1d1e3
palette = 7=#ffffff
palette = 8=#626880
palette = 9=#e67172
palette = 10=#8ec772
palette = 11=#d9ba73
palette = 12=#7b9ef0
palette = 13=#f2a4db
palette = 14=#5abfb5
palette = 15=#b5bfe2
keybind = all:ctrl+shift+period=text:\x1b\x1f\x4c\x23\x1f
'';
};
}

View file

@ -0,0 +1,48 @@
gtk-single-instance = true
gtk-titlebar = false
window-decoration = server
quit-after-last-window-closed = true
gtk-adwaita = false
# font-family = ${system-font}
font-family = Consolas
font-size = 14
app-notifications = no-clipboard-copy
macos-option-as-alt = left
theme = nightfox
# theme = gruber-darker
# theme = xcodelighthc
# theme = zenburned
# font-family = Iosevka Nerd Font Mono
# font-size = 13
# # background = #062329
# background = #072626
# # foreground = #d1b897
# foreground = #d3b58d
# cursor-color = #ffffff
# # cursor-text = #d1b897
# cursor-text = #d3b58d
# # selection-background = #0000ff
# # selection-foreground = #d1b897
# selection-background = #0000ff
# selection-foreground = #d3b58d
# # palette = 0=#062329
# palette = 0=#072626
# # palette = 1=#0b3335
# # palette = 2=#0000ff
# palette = 3=#44b340
# palette = 4=#8cde94
# # palette = 5=#d1b897
# palette = 5=#d3b58d
# palette = 6=#c1d1e3
# palette = 7=#ffffff
# palette = 8=#626880
# palette = 9=#e67172
# palette = 10=#8ec772
# palette = 11=#d9ba73
# palette = 12=#7b9ef0
# palette = 13=#f2a4db
# palette = 14=#5abfb5
# palette = 15=#b5bfe2
keybind = all:ctrl+shift+period=text:\x1b\x1f\x4c\x23\x1f

27
home/ghostty/default.nix Normal file
View file

@ -0,0 +1,27 @@
{
config,
pkgs,
inputs,
lib,
system-font,
dots,
...
}:
{
options.custom.gui = with lib; {
ghostty = {
enable = mkEnableOption "Enable ghostty";
};
};
config = lib.mkIf config.custom.gui.ghostty.enable {
home.packages = lib.mkIf pkgs.stdenv.isLinux (
with pkgs;
[
inputs.ghostty.packages."${system}".default
]
);
xdg.configFile."ghostty".source = config.lib.file.mkOutOfStoreSymlink "${dots}/home/ghostty/config";
};
}

View file

@ -12,7 +12,7 @@
imports = [ imports = [
./i3 ./i3
./kitty.nix ./kitty.nix
./ghostty.nix ./ghostty
]; ];
options.custom.gui = with lib; { options.custom.gui = with lib; {

View file

@ -11,11 +11,21 @@ local command_history = {}
local HISTORY_FILE = vim.fn.stdpath 'data' .. '/compile_history' local HISTORY_FILE = vim.fn.stdpath 'data' .. '/compile_history'
local MAX_HISTORY_SIZE = 200 local MAX_HISTORY_SIZE = 200
--- @class CompileInputKeymaps
--- @field next string? Cycle to next completion candidate
--- @field prev string? Cycle to previous completion candidate
--- @field confirm string? Confirm and run compile command
--- @field close (string|string[])? Close compile prompt
--- @field delete_component string? Delete path component
--- @field history_prev string? Previous command in history
--- @field history_next string? Next command in history
--- @class CompileConfig --- @class CompileConfig
--- @field on_success? fun(qf_list: table) --- @field on_success? fun(qf_list: table)
--- @field on_error? fun(qf_list: table, exit_code: number) --- @field on_error? fun(qf_list: table, exit_code: number)
--- @field on_exit? fun(qf_list: table, exit_code: number) --- @field on_exit? fun(qf_list: table, exit_code: number)
--- @field keymaps? table<string, string|false> --- @field buffer_keymaps? table<string, string|false> Keymaps for compilation buffer
--- @field input_keymaps? CompileInputKeymaps Keymaps for input prompt
--- @field split_mode? 'auto'|'horizontal'|'vertical-right'|'vertical-left' --- @field split_mode? 'auto'|'horizontal'|'vertical-right'|'vertical-left'
--- @field min_width_for_vertical? number --- @field min_width_for_vertical? number
--- @field prompt? string --- @field prompt? string
@ -25,10 +35,20 @@ local config = {
on_success = nil, on_success = nil,
on_error = nil, on_error = nil,
on_exit = nil, on_exit = nil,
keymaps = { buffer_keymaps = {
close = 'q', close = 'q',
recompile = 'g', recompile = 'g',
}, },
input_keymaps = {
next = '<C-n>',
prev = '<C-p>',
complete = '<Tab>',
confirm = '<CR>',
close = { '<C-c>', '<Esc>' },
delete_component = '<M-BS>',
history_prev = '<M-p>',
history_next = '<M-n>',
},
split_mode = 'auto', split_mode = 'auto',
min_width_for_vertical = 160, min_width_for_vertical = 160,
prompt = 'Compile command', prompt = 'Compile command',
@ -527,17 +547,13 @@ function M.compile()
local pos = #table.concat(parts, '') local pos = #table.concat(parts, '')
local max_display = 8 local max_display = 8
-- Add opening bracket
table.insert(parts, ' [')
pos = pos + 2
for i, match in ipairs(matches) do for i, match in ipairs(matches) do
if i > max_display then break end if i > max_display then break end
if i > 1 then
table.insert(parts, ' | ')
pos = pos + 3
else
table.insert(parts, ' | ')
pos = pos + 3
end
local filter_start, filter_end = nil, nil local filter_start, filter_end = nil, nil
if last_word ~= '' then if last_word ~= '' then
filter_start, filter_end = match:lower():find(last_word:lower(), 1, true) filter_start, filter_end = match:lower():find(last_word:lower(), 1, true)
@ -553,9 +569,22 @@ function M.compile()
table.insert(parts, match) table.insert(parts, match)
pos = pos + #match pos = pos + #match
-- Add pipe separator between candidates (but not after the last one shown)
if i < math.min(#matches, max_display) then
table.insert(parts, ' | ')
pos = pos + 3
end
end end
if #matches > max_display then table.insert(parts, ' | ...') end -- Add ellipsis if there are more matches than max_display
if #matches > max_display then
table.insert(parts, ' | ...')
pos = pos + 6
end
-- Add closing bracket
table.insert(parts, ']')
end end
local full_text = table.concat(parts, '') local full_text = table.concat(parts, '')
@ -632,6 +661,7 @@ function M.compile()
vim.schedule(function() vim.api.nvim_win_set_cursor(input_win, { 1, prompt_len + #current_input }) end) vim.schedule(function() vim.api.nvim_win_set_cursor(input_win, { 1, prompt_len + #current_input }) end)
local last_input = current_input local last_input = current_input
local saved_input = nil
vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, { vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, {
buffer = input_buf, buffer = input_buf,
@ -655,8 +685,8 @@ function M.compile()
end end
local input_part = line:sub(prompt_len + 1) local input_part = line:sub(prompt_len + 1)
local pipe_pos = input_part:find ' | ' local bracket_pos = input_part:find ' %['
if pipe_pos then input_part = input_part:sub(1, pipe_pos - 1) end if bracket_pos then input_part = input_part:sub(1, bracket_pos - 1) end
if input_part ~= last_input then if input_part ~= last_input then
current_input = input_part current_input = input_part
@ -687,99 +717,141 @@ function M.compile()
local opts = { buffer = input_buf, nowait = true, silent = true } local opts = { buffer = input_buf, nowait = true, silent = true }
vim.keymap.set('i', '<Tab>', function() -- Cycle to next completion candidate
if #matches == 0 then if config.input_keymaps.next then
matches = get_matches(current_input) vim.keymap.set('i', config.input_keymaps.next, function()
if #matches == 0 then return end if #matches == 0 then
end matches = get_matches(current_input)
if #matches == 0 then return end
match_index = (match_index % #matches) + 1
local words = vim.split(current_input, '%s+')
words[#words] = matches[match_index]
current_input = table.concat(words, ' ')
last_input = current_input
vim.schedule(update_display)
end, opts)
vim.keymap.set('i', '<S-Tab>', function()
if #matches == 0 then
matches = get_matches(current_input)
if #matches == 0 then return end
end
match_index = match_index - 1
if match_index < 1 then match_index = #matches end
local words = vim.split(current_input, '%s+')
words[#words] = matches[match_index]
current_input = table.concat(words, ' ')
last_input = current_input
vim.schedule(update_display)
end, opts)
vim.keymap.set('i', '<C-p>', function()
if #command_history > 0 then
if history_index == 0 then
current_input = get_input()
last_input = current_input
end end
if history_index < #command_history then
history_index = history_index + 1 match_index = (match_index % #matches) + 1
current_input = command_history[#command_history - history_index + 1] local words = vim.split(current_input, '%s+')
words[#words] = matches[match_index]
current_input = table.concat(words, ' ')
last_input = current_input
vim.schedule(update_display)
end, opts)
end
-- Cycle to previous completion candidate
if config.input_keymaps.prev then
vim.keymap.set('i', config.input_keymaps.prev, function()
if #matches == 0 then
matches = get_matches(current_input)
if #matches == 0 then return end
end
match_index = match_index - 1
if match_index < 1 then match_index = #matches end
local words = vim.split(current_input, '%s+')
words[#words] = matches[match_index]
current_input = table.concat(words, ' ')
last_input = current_input
vim.schedule(update_display)
end, opts)
end
-- Complete to selected candidate
if config.input_keymaps.complete then
vim.keymap.set('i', config.input_keymaps.complete, function()
if #matches == 0 then
matches = get_matches(current_input)
if #matches == 0 then return '' end
end
local match = match_index > 0 and matches[match_index] or matches[1]
local words = vim.split(current_input, '%s+')
words[#words] = match
current_input = table.concat(words, ' ')
last_input = current_input
match_index = 0
matches = {}
vim.schedule(update_display)
return ''
end, vim.tbl_extend('force', opts, { expr = true }))
end
-- Previous command in history
if config.input_keymaps.history_prev then
vim.keymap.set('i', config.input_keymaps.history_prev, function()
if #command_history > 0 then
if history_index == 0 then
saved_input = get_input()
end
if history_index < #command_history then
history_index = history_index + 1
current_input = command_history[#command_history - history_index + 1]
last_input = current_input
vim.schedule(update_display)
end
end
return ''
end, vim.tbl_extend('force', opts, { expr = true }))
end
-- Next command in history
if config.input_keymaps.history_next then
vim.keymap.set('i', config.input_keymaps.history_next, function()
if history_index > 0 then
history_index = history_index - 1
if history_index == 0 then
current_input = saved_input or get_input()
saved_input = nil
else
current_input = command_history[#command_history - history_index + 1]
end
last_input = current_input last_input = current_input
vim.schedule(update_display) vim.schedule(update_display)
end end
end return ''
return '' end, vim.tbl_extend('force', opts, { expr = true }))
end, vim.tbl_extend('force', opts, { expr = true })) end
vim.keymap.set('i', '<C-n>', function() -- Confirm and run compile command
if history_index > 0 then if config.input_keymaps.confirm then
history_index = history_index - 1 vim.keymap.set('i', config.input_keymaps.confirm, function()
if history_index == 0 then if current_input and current_input ~= '' then
current_input = get_input() append_to_history(current_input)
else vim.schedule(function()
current_input = command_history[#command_history - history_index + 1] close()
run_compile(current_input)
end)
end end
return ''
end, vim.tbl_extend('force', opts, { expr = true }))
end
-- Close compile prompt
---@type string[]
local close_keys = type(config.input_keymaps.close) == 'table' and config.input_keymaps.close --[[@as string[] ]] or { config.input_keymaps.close }
for _, key in ipairs(close_keys) do
if key then vim.keymap.set({ 'i', 'n' }, key, function() vim.schedule(close) end, opts) end
end
-- Delete path component
if config.input_keymaps.delete_component then
vim.keymap.set('i', config.input_keymaps.delete_component, function()
local new_pos = 0
local found_non_sep = false
for i = #current_input, 1, -1 do
local char = current_input:sub(i, i)
local is_sep = char:match '[/%._%- ]'
if not found_non_sep and not is_sep then
found_non_sep = true
elseif found_non_sep and is_sep then
new_pos = i
break
end
end
current_input = current_input:sub(1, new_pos)
last_input = current_input last_input = current_input
vim.schedule(update_display) vim.schedule(update_display)
end return ''
return '' end, vim.tbl_extend('force', opts, { expr = true }))
end, vim.tbl_extend('force', opts, { expr = true })) end
vim.keymap.set('i', '<CR>', function()
if current_input and current_input ~= '' then
append_to_history(current_input)
vim.schedule(function()
close()
run_compile(current_input)
end)
end
return ''
end, vim.tbl_extend('force', opts, { expr = true }))
vim.keymap.set({ 'i', 'n' }, '<Esc>', function() vim.schedule(close) end, opts)
vim.keymap.set({ 'i', 'n' }, '<C-c>', function() vim.schedule(close) end, opts)
vim.keymap.set('i', '<M-BS>', function()
local new_pos = 0
local found_non_sep = false
for i = #current_input, 1, -1 do
local char = current_input:sub(i, i)
local is_sep = char:match '[/%._%- ]'
if not found_non_sep and not is_sep then
found_non_sep = true
elseif found_non_sep and is_sep then
new_pos = i
break
end
end
current_input = current_input:sub(1, new_pos)
last_input = current_input
vim.schedule(update_display)
return ''
end, vim.tbl_extend('force', opts, { expr = true }))
vim.cmd 'startinsert!' vim.cmd 'startinsert!'
end end
@ -811,8 +883,8 @@ function M.setup(opts)
vim.api.nvim_create_autocmd('FileType', { vim.api.nvim_create_autocmd('FileType', {
pattern = 'compilation', pattern = 'compilation',
callback = function() callback = function()
if config.keymaps.close then vim.keymap.set('n', config.keymaps.close, '<cmd>close<cr>', { buffer = true, desc = 'Close compilation buffer' }) end if config.buffer_keymaps.close then vim.keymap.set('n', config.buffer_keymaps.close, '<cmd>close<cr>', { buffer = true, desc = 'Close compilation buffer' }) end
if config.keymaps.recompile then vim.keymap.set('n', config.keymaps.recompile, M.recompile, { buffer = true, desc = 'Recompile' }) end if config.buffer_keymaps.recompile then vim.keymap.set('n', config.buffer_keymaps.recompile, M.recompile, { buffer = true, desc = 'Recompile' }) end
local function jump_to_error() local function jump_to_error()
local bufnr = vim.api.nvim_get_current_buf() local bufnr = vim.api.nvim_get_current_buf()

View file

@ -199,17 +199,13 @@ function M.open_dir(start_path)
if #matches > 0 and show_matches then if #matches > 0 and show_matches then
local pos = #table.concat(parts, '') local pos = #table.concat(parts, '')
-- Add opening bracket
table.insert(parts, ' [')
pos = pos + 2
for i, match in ipairs(matches) do for i, match in ipairs(matches) do
if i > config.max_matches then break end if i > config.max_matches then break end
if i > 1 then
table.insert(parts, ' | ')
pos = pos + 3
else
table.insert(parts, ' | ')
pos = pos + 3
end
local sep = match.type == 'directory' and '/' or '' local sep = match.type == 'directory' and '/' or ''
local item = match.name .. sep local item = match.name .. sep
@ -229,9 +225,22 @@ function M.open_dir(start_path)
table.insert(parts, item) table.insert(parts, item)
pos = pos + #item pos = pos + #item
-- Add pipe separator between candidates (but not after the last one shown)
if i < math.min(#matches, config.max_matches) then
table.insert(parts, ' | ')
pos = pos + 3
end
end end
if #matches > config.max_matches then table.insert(parts, ' | ...') end -- Add ellipsis if there are more matches than max_matches
if #matches > config.max_matches then
table.insert(parts, ' | ...')
pos = pos + 6
end
-- Add closing bracket
table.insert(parts, ']')
end end
local full_text = table.concat(parts, '') local full_text = table.concat(parts, '')
@ -332,8 +341,8 @@ function M.open_dir(start_path)
if not line:match '^Find file: ' then return end if not line:match '^Find file: ' then return end
local path_part = line:sub(12) local path_part = line:sub(12)
local pipe_pos = path_part:find ' | ' local bracket_pos = path_part:find ' %['
if pipe_pos then path_part = path_part:sub(1, pipe_pos - 1) end if bracket_pos then path_part = path_part:sub(1, bracket_pos - 1) end
if path_part ~= last_input then if path_part ~= last_input then
current_input = path_part current_input = path_part