diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f2313f77..06197197 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,9 +29,9 @@ jobs: # yazi-fm is the `yazi` executable crate: yazi-fm git: https://github.com/sxyazi/yazi - # feat: ownership linemode (#1238) - # https://github.com/sxyazi/yazi/commit/11547eefe0346006a1a82455577784a34d67c9b7 - commit: 11547eefe0346006a1a82455577784a34d67c9b7 + # refactor: reimplement the signal system (#1307) + # https://github.com/sxyazi/yazi/commit/d6081fbe6f57 + commit: d6081fbe6f57 - name: Compile and install yazi from source uses: baptiste0928/cargo-install@v3 @@ -39,9 +39,9 @@ jobs: # yazi-cli is the `ya` command line interface crate: yazi-cli git: https://github.com/sxyazi/yazi - # feat: ownership linemode (#1238) - # https://github.com/sxyazi/yazi/commit/11547eefe0346006a1a82455577784a34d67c9b7 - commit: 11547eefe0346006a1a82455577784a34d67c9b7 + # refactor: reimplement the signal system (#1307) + # https://github.com/sxyazi/yazi/commit/d6081fbe6f57 + commit: d6081fbe6f57 - name: Run tests uses: nvim-neorocks/nvim-busted-action@v1 diff --git a/README.md b/README.md index 5d5600ba..c0e5d477 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,9 @@ You can optionally configure yazi.nvim by setting any of the options below. -- https://github.com/mikavilpas/yazi.nvim/pull/152 use_ya_for_events_reading = false, + -- an upcoming optional feature + use_yazi_client_id_flag = false, + -- an upcoming optional feature. See -- https://github.com/mikavilpas/yazi.nvim/pull/180 highlight_groups = { diff --git a/integration-tests/test-environment/config-modifications/modify_yazi_config_to_use_ya_as_event_reader.lua b/integration-tests/test-environment/config-modifications/modify_yazi_config_to_use_ya_as_event_reader.lua index 8ff77a47..17b57b9c 100644 --- a/integration-tests/test-environment/config-modifications/modify_yazi_config_to_use_ya_as_event_reader.lua +++ b/integration-tests/test-environment/config-modifications/modify_yazi_config_to_use_ya_as_event_reader.lua @@ -4,5 +4,6 @@ require('yazi').setup( ---@type YaziConfig { use_ya_for_events_reading = true, + use_yazi_client_id_flag = true, } ) diff --git a/lua/yazi/config.lua b/lua/yazi/config.lua index ec4f2a34..b84f5d90 100644 --- a/lua/yazi/config.lua +++ b/lua/yazi/config.lua @@ -12,6 +12,7 @@ function M.default() open_for_directories = false, -- NOTE: right now this is opt-in, but will be the default in the future use_ya_for_events_reading = false, + use_yazi_client_id_flag = false, enable_mouse_support = false, open_file_function = openers.open_file, set_keymappings_function = M.default_set_keymappings_function, diff --git a/lua/yazi/health.lua b/lua/yazi/health.lua index fcab9ed4..71900375 100644 --- a/lua/yazi/health.lua +++ b/lua/yazi/health.lua @@ -47,9 +47,22 @@ return { vim.health.info('yazi.nvim log file is at ' .. logfile_location) vim.health.info(' hint: use `gf` to open the file path under the cursor') + local config = require('yazi').config + + if config.use_yazi_client_id_flag == true then + local output = vim.fn.system('yazi --help') + + if output:find('--client-id', 1, true) == nil then + vim.health.warn( + 'You have enabled `use_yazi_client_id_flag` in your config, which means using the `--client-id` flag with yazi. However, this flag is not found in the `yazi --help` output. Please upgrade to the newest version of yazi or disable `use_yazi_client_id_flag`.' + ) + vim.health.info(string.format('`yazi --help` output: %s', output)) + end + end + -- TODO validate that the highlight_config is present in the configuration - if require('yazi').config.use_ya_for_events_reading == true then + if config.use_ya_for_events_reading == true then if vim.fn.executable('ya') ~= 1 then vim.health.error( 'You have opted in to using `ya` for events reading, but `ya` is not found on PATH. Please install `ya` or disable `use_ya_for_events_reading` in your config.' diff --git a/lua/yazi/process/legacy_events_from_file.lua b/lua/yazi/process/legacy_events_from_file.lua index 7dcc3bc2..bd3f85cd 100644 --- a/lua/yazi/process/legacy_events_from_file.lua +++ b/lua/yazi/process/legacy_events_from_file.lua @@ -15,7 +15,7 @@ function LegacyEventReadingFromEventFile:new(config) end ---@param path Path -function LegacyEventReadingFromEventFile:get_yazi_command(path) +function LegacyEventReadingFromEventFile:get_yazi_command(path, _) return string.format( 'yazi %s --local-events "rename,delete,trash,move,cd" --chooser-file "%s" > "%s"', vim.fn.shellescape(path.filename), diff --git a/lua/yazi/process/ya_process.lua b/lua/yazi/process/ya_process.lua index df4b3ddc..d81edc49 100644 --- a/lua/yazi/process/ya_process.lua +++ b/lua/yazi/process/ya_process.lua @@ -9,8 +9,9 @@ local highlight_hovered_buffer = ---@class (exact) YaProcess ---@field public events YaziEvent[] "The events that have been received from yazi" ----@field public new fun(config: YaziConfig): YaProcess +---@field public new fun(config: YaziConfig, yazi_id: string): YaProcess ---@field private config YaziConfig +---@field private yazi_id string ---@field private ya_process vim.SystemObj ---@field private retries integer local YaProcess = {} @@ -18,8 +19,10 @@ local YaProcess = {} YaProcess.__index = YaProcess ---@param config YaziConfig -function YaProcess.new(config) +---@param yazi_id string +function YaProcess.new(config, yazi_id) local self = setmetatable({}, YaProcess) + self.yazi_id = yazi_id self.config = config self.events = {} self.retries = 0 @@ -28,11 +31,13 @@ function YaProcess.new(config) end ---@param path Path -function YaProcess:get_yazi_command(path) +---@param yazi_id string +function YaProcess:get_yazi_command(path, yazi_id) return string.format( - 'yazi %s --chooser-file "%s"', + 'yazi %s --chooser-file "%s" --client-id "%s"', vim.fn.shellescape(path.filename), - self.config.chosen_file_path + self.config.chosen_file_path, + yazi_id ) end diff --git a/lua/yazi/types.lua b/lua/yazi/types.lua index 6b8c0021..f0162154 100644 --- a/lua/yazi/types.lua +++ b/lua/yazi/types.lua @@ -7,6 +7,7 @@ ---@field public chosen_file_path? string "the path to a temporary file that will be created by yazi to store the chosen file path" ---@field public events_file_path? string "the path to a temporary file that will be created by yazi to store events. A random path will be used by default" ---@field public use_ya_for_events_reading? boolean "use `ya`, the yazi command line application to read events from the yazi process. Right now this is opt-in, but will be the default in the future" +---@field public use_yazi_client_id_flag? boolean "use the `--client-id` flag with yazi, allowing communication with that specific instance as opposed to all yazis on the system" ---@field public enable_mouse_support? boolean ---@field public open_file_function? fun(chosen_file: string, config: YaziConfig, state: YaziClosedState): nil "a function that will be called when a file is chosen in yazi" ---@field public set_keymappings_function? fun(buffer: integer, config: YaziConfig): nil "the function that will set the keymappings for the yazi floating window. It will be called after the floating window is created." diff --git a/lua/yazi/yazi_process.lua b/lua/yazi/yazi_process.lua index 631952f8..1f039e78 100644 --- a/lua/yazi/yazi_process.lua +++ b/lua/yazi/yazi_process.lua @@ -26,13 +26,19 @@ function YaziProcess:start(config, path, on_exit) config.use_ya_for_events_reading ) ) + + -- The YAZI_ID of the yazi process, used to uniquely identify this specific + -- instance, so that we can communicate with it specifically, instead of + -- possibly multiple other yazis that are running on this computer. + local yazi_id = string.format('%.0f', vim.uv.hrtime()) + self.event_reader = config.use_ya_for_events_reading == true - and YaProcess.new(config) + and YaProcess.new(config, yazi_id) or LegacyEventReadingFromEventFile:new(config) - local yazi_cmd = self.event_reader:get_yazi_command(path) + local yazi_cmd = self.event_reader:get_yazi_command(path, yazi_id) + Log:debug(string.format('Opening yazi with the command: (%s).', yazi_cmd)) - Log:debug(string.format('Opening yazi with the command: (%s)', yazi_cmd)) self.yazi_job_id = vim.fn.termopen(yazi_cmd, { on_exit = function(_, code) self.event_reader:kill() diff --git a/spec/yazi/health_spec.lua b/spec/yazi/health_spec.lua index 09c9ee73..d687c9d8 100644 --- a/spec/yazi/health_spec.lua +++ b/spec/yazi/health_spec.lua @@ -15,6 +15,19 @@ local function assert_buffer_contains_text(needle) assert(found, message) end +local function assert_buffer_does_not_contain_text(needle) + local buffer_text = vim.api.nvim_buf_get_lines(0, 0, -1, false) + local text = table.concat(buffer_text, '\n') + local message = string.format( + "Expected the main string to not contain the substring.\nMain string: '%s'\nSubstring: '%s'", + text, + needle + ) + + local found = string.find(text, needle, 1, true) ~= nil + assert.is_false(found, message) +end + -- make nvim find the health check file so that it can be executed by :checkhealth -- without this, the health check will not be found vim.opt.rtp:append('.') @@ -28,6 +41,22 @@ describe('the healthcheck', function() snapshot = assert:snapshot() mock_app_versions = { ['yazi'] = 'yazi 0.2.5 (f5a7ace 2024-06-23)', + ['yazi --help'] = [[Usage: yazi [OPTIONS] [ENTRY] + +Arguments: + [ENTRY] Set the current working entry + +Options: + --cwd-file Write the cwd on exit to this file + --chooser-file Write the selected files to this file on open fired + --clear-cache Clear the cache directory + --client-id Use the specified client ID, must be a globally unique number + --local-events Report the specified local events to stdout + --remote-events Report the specified remote events to stdout + --debug Print debug information + -V, --version Print version + -h, --help Print help + ]], ['ya'] = 'Ya 0.2.5 (f5a7ace 2024-06-23)', ['nvim-0.10.0'] = true, } @@ -49,8 +78,10 @@ describe('the healthcheck', function() return mock_app_versions['yazi'] elseif command == 'ya --version' then return mock_app_versions['ya'] + elseif command == 'yazi --help' then + return mock_app_versions['yazi --help'] else - error('unexpected command: ' .. command) + error('the command is not mocked in the test: ' .. vim.inspect(command)) end end) end) @@ -138,4 +169,61 @@ describe('the healthcheck', function() 'WARNING The versions of `yazi` and `ya` do not match.' ) end) + + describe('the checks for `use_yazi_client_id_flag`', function() + local yazi_help_output_with_client_id_flag_missing = + [[Usage: yazi [OPTIONS] [ENTRY] + +Arguments: + [ENTRY] Set the current working entry + +Options: + --cwd-file Write the cwd on exit to this file + --chooser-file Write the selected files to this file on open fired + --clear-cache Clear the cache directory + --local-events Report the specified local events to stdout + --remote-events Report the specified remote events to stdout + --debug Print debug information + -V, --version Print version + -h, --help Print help + ]] + + before_each(function() end) + + it( + 'warns when the `--client-id` flag is not found in the yazi --help output', + function() + mock_app_versions['yazi --help'] = + yazi_help_output_with_client_id_flag_missing + require('yazi').setup({ use_yazi_client_id_flag = true }) + vim.cmd('checkhealth yazi') + + assert_buffer_contains_text( + 'You have enabled `use_yazi_client_id_flag` in your config, which means using the `--client-id` flag with yazi. However, this flag is not found in the `yazi --help` output. Please upgrade to the newest version of yazi or disable `use_yazi_client_id_flag`.' + ) + end + ) + + it( + "does not warn when `use_yazi_client_id_flag` is not set and yazi doesn't support --client-id", + function() + mock_app_versions['yazi --help'] = + yazi_help_output_with_client_id_flag_missing + require('yazi').setup({ use_yazi_client_id_flag = false }) + vim.cmd('checkhealth yazi') + + assert_buffer_does_not_contain_text('use_yazi_client_id_flag') + end + ) + + it( + 'does not warn when the `--client-id` flag is found in the yazi --help output', + function() + require('yazi').setup({ use_yazi_client_id_flag = true }) + vim.cmd('checkhealth yazi') + + assert_buffer_does_not_contain_text('use_yazi_client_id_flag') + end + ) + end) end)