diff --git a/lua/blink-cmp-ghostty.lua b/lua/blink-cmp-ghostty.lua index 9eb94ce..abfcd98 100644 --- a/lua/blink-cmp-ghostty.lua +++ b/lua/blink-cmp-ghostty.lua @@ -13,31 +13,9 @@ function M.new() return setmetatable({}, { __index = M }) end -local ghostty_config_dirs = { - vim.fn.expand('$XDG_CONFIG_HOME/ghostty'), - vim.fn.expand('$HOME/.config/ghostty'), - '/etc/ghostty', -} - ---@return boolean function M.enabled() - if vim.bo.filetype == 'ghostty' then - return true - end - if vim.bo.filetype ~= 'config' and vim.bo.filetype ~= '' then - return false - end - local path = vim.api.nvim_buf_get_name(0) - if path == '' then - return false - end - local real = vim.uv.fs_realpath(path) or path - for _, dir in ipairs(ghostty_config_dirs) do - if real:find(dir, 1, true) == 1 then - return true - end - end - return false + return vim.bo.filetype == 'ghostty' end ---@param stdout string @@ -67,25 +45,28 @@ local function parse_keys(stdout) return items end ----@return string? -function M.bash_completion_path() +---@return table +local function parse_enums() local bin = vim.fn.exepath('ghostty') if bin == '' then - return nil + return {} end local real = vim.uv.fs_realpath(bin) if not real then - return nil + return {} end local prefix = real:match('(.*)/bin/ghostty$') if not prefix then - return nil + return {} end - return prefix .. '/share/bash-completion/completions/ghostty.bash' -end + local path = prefix .. '/share/bash-completion/completions/ghostty.bash' + local fd = io.open(path, 'r') + if not fd then + return {} + end + local content = fd:read('*a') + fd:close() ----@return table -local function parse_enums(content) local enums = {} for key, values in content:gmatch('%-%-([a-z][a-z0-9-]*)%) [^\n]* compgen %-W "([^"]+)"') do local vals = {} @@ -102,9 +83,6 @@ end ---@param ctx blink.cmp.Context ---@param callback fun(response: blink.cmp.CompletionResponse) local function respond(ctx, callback) - if not keys_cache or not enums_cache then - return - end local line = ctx.line local col = ctx.cursor[2] local eq_pos = line:find('=') @@ -151,56 +129,17 @@ function M:get_completions(ctx, callback) pending[#pending + 1] = { ctx = ctx, callback = callback } if not loading then loading = true - local config_out, enums_content - local remaining = 2 - - local function on_all_done() - remaining = remaining - 1 - if remaining > 0 then - return - end + vim.system({ 'ghostty', '+show-config', '--docs' }, {}, function(result) vim.schedule(function() - keys_cache = parse_keys(config_out) - enums_cache = parse_enums(enums_content) + keys_cache = parse_keys(result.stdout or '') + enums_cache = parse_enums() loading = false for _, p in ipairs(pending) do respond(p.ctx, p.callback) end pending = {} end) - end - - vim.system({ 'ghostty', '+show-config', '--docs' }, {}, function(result) - config_out = result.stdout or '' - on_all_done() end) - - local path = M.bash_completion_path() - if not path then - enums_content = '' - on_all_done() - else - vim.uv.fs_open(path, 'r', 438, function(err, fd) - if err or not fd then - enums_content = '' - on_all_done() - return - end - vim.uv.fs_fstat(fd, function(err2, stat) - if err2 or not stat then - vim.uv.fs_close(fd) - enums_content = '' - on_all_done() - return - end - vim.uv.fs_read(fd, stat.size, 0, function(_, data) - vim.uv.fs_close(fd) - enums_content = data or '' - on_all_done() - end) - end) - end) - end end return function() end end diff --git a/lua/blink-cmp-ghostty/health.lua b/lua/blink-cmp-ghostty/health.lua deleted file mode 100644 index 5db565d..0000000 --- a/lua/blink-cmp-ghostty/health.lua +++ /dev/null @@ -1,47 +0,0 @@ -local M = {} - -function M.check() - vim.health.start('blink-cmp-ghostty') - - local ok = pcall(require, 'blink.cmp') - if ok then - vim.health.ok('blink.cmp is installed') - else - vim.health.error('blink.cmp is not installed') - end - - local bin = vim.fn.exepath('ghostty') - if bin ~= '' then - vim.health.ok('ghostty executable found: ' .. bin) - else - vim.health.error('ghostty executable not found') - return - end - - local result = vim.system({ 'ghostty', '+show-config', '--docs' }):wait() - if result.code == 0 and result.stdout and result.stdout ~= '' then - vim.health.ok('ghostty +show-config --docs produces output') - else - vim.health.warn( - 'ghostty +show-config --docs failed (config key documentation will be unavailable)' - ) - end - - local source = require('blink-cmp-ghostty') - local path = source.bash_completion_path() - if not path then - vim.health.warn('could not resolve bash completion path (enum completions will be unavailable)') - return - end - local fd = io.open(path, 'r') - if fd then - fd:close() - vim.health.ok('bash completion file found: ' .. path) - else - vim.health.warn( - 'bash completion file not found at ' .. path .. ' (enum completions will be unavailable)' - ) - end -end - -return M diff --git a/lua/blink-cmp-ghostty/types.lua b/lua/blink-cmp-ghostty/types.lua deleted file mode 100644 index d311414..0000000 --- a/lua/blink-cmp-ghostty/types.lua +++ /dev/null @@ -1,16 +0,0 @@ ----@class blink.cmp.Source - ----@class blink.cmp.CompletionItem ----@field label string ----@field kind? integer ----@field documentation? {kind: string, value: string} ----@field filterText? string - ----@class blink.cmp.Context ----@field line string ----@field cursor integer[] - ----@class blink.cmp.CompletionResponse ----@field is_incomplete_forward? boolean ----@field is_incomplete_backward? boolean ----@field items blink.cmp.CompletionItem[] diff --git a/spec/ghostty_spec.lua b/spec/ghostty_spec.lua index 5ef7a2a..fae7bab 100644 --- a/spec/ghostty_spec.lua +++ b/spec/ghostty_spec.lua @@ -29,22 +29,14 @@ local function mock_system() on_exit(result) return {} end - return { - wait = function() - return result - end, - } + return { wait = function() return result end } end local result = { stdout = '', code = 1 } if on_exit then on_exit(result) return {} end - return { - wait = function() - return result - end, - } + return { wait = function() return result end } end vim.schedule = function(fn) fn() @@ -55,15 +47,10 @@ local function mock_system() end end -local MOCK_FD = 99 - local function mock_enums() local original_exepath = vim.fn.exepath local original_realpath = vim.uv.fs_realpath - local original_fs_open = vim.uv.fs_open - local original_fs_fstat = vim.uv.fs_fstat - local original_fs_read = vim.uv.fs_read - local original_fs_close = vim.uv.fs_close + local original_open = io.open vim.fn.exepath = function(name) if name == 'ghostty' then @@ -77,41 +64,22 @@ local function mock_enums() end return original_realpath(path) end - vim.uv.fs_open = function(path, flags, mode, callback) + io.open = function(path, mode) if path:match('ghostty%.bash$') then - callback(nil, MOCK_FD) - return + return { + read = function() + return BASH_COMPLETION + end, + close = function() end, + } end - return original_fs_open(path, flags, mode, callback) - end - vim.uv.fs_fstat = function(fd, callback) - if fd == MOCK_FD then - callback(nil, { size = #BASH_COMPLETION }) - return - end - return original_fs_fstat(fd, callback) - end - vim.uv.fs_read = function(fd, size, offset, callback) - if fd == MOCK_FD then - callback(nil, BASH_COMPLETION) - return - end - return original_fs_read(fd, size, offset, callback) - end - vim.uv.fs_close = function(fd, ...) - if fd == MOCK_FD then - return true - end - return original_fs_close(fd, ...) + return original_open(path, mode) end return function() vim.fn.exepath = original_exepath vim.uv.fs_realpath = original_realpath - vim.uv.fs_open = original_fs_open - vim.uv.fs_fstat = original_fs_fstat - vim.uv.fs_read = original_fs_read - vim.uv.fs_close = original_fs_close + io.open = original_open end end @@ -137,43 +105,6 @@ describe('blink-cmp-ghostty', function() helpers.delete_buffer(bufnr) end) - it('returns true for config filetype in ghostty config dir', function() - local source = require('blink-cmp-ghostty') - local bufnr = vim.api.nvim_create_buf(false, true) - vim.api.nvim_set_current_buf(bufnr) - vim.api.nvim_set_option_value('filetype', 'config', { buf = bufnr }) - local config_path = vim.fn.expand('$HOME/.config/ghostty/config') - vim.api.nvim_buf_set_name(bufnr, config_path) - local original_realpath = vim.uv.fs_realpath - vim.uv.fs_realpath = function(p) - if p == config_path then - return config_path - end - return original_realpath(p) - end - assert.is_true(source.enabled()) - vim.uv.fs_realpath = original_realpath - helpers.delete_buffer(bufnr) - end) - - it('returns false for config filetype outside ghostty dir', function() - local source = require('blink-cmp-ghostty') - local bufnr = vim.api.nvim_create_buf(false, true) - vim.api.nvim_set_current_buf(bufnr) - vim.api.nvim_set_option_value('filetype', 'config', { buf = bufnr }) - vim.api.nvim_buf_set_name(bufnr, '/tmp/some-other/config') - local original_realpath = vim.uv.fs_realpath - vim.uv.fs_realpath = function(p) - if p == '/tmp/some-other/config' then - return '/tmp/some-other/config' - end - return original_realpath(p) - end - assert.is_false(source.enabled()) - vim.uv.fs_realpath = original_realpath - helpers.delete_buffer(bufnr) - end) - it('returns false for other filetypes', function() local bufnr = helpers.create_buffer({}, 'lua') local source = require('blink-cmp-ghostty')