Skip to content

Commit 6295532

Browse files
committed
fix: report parent directory of input_path as last_directory
Background ========== When yazi is started too late, it can happen that we don't know what the last_directory was when yazi has exited. When this happens, yazi has already reported its `cd` event before `ya` starts and yazi.nvim cannot capture it. The issue can be tracked in sxyazi/yazi#1314 Issue ===== Currently yazi.nvim works around this limitation by using the parent directory of the input_path as the last_directory since it's a good guess. However, it looks like this has never worked reliably due to a bug in the implementation. The correct directory was calculated, but it was not assigned to the last_directory field in the state - it was ignored and had no effect. Solution ======== Assign the correct directory to the last_directory field in the state.
1 parent 907b537 commit 6295532

File tree

3 files changed

+112
-33
lines changed

3 files changed

+112
-33
lines changed

lua/yazi.lua

+3-1
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,17 @@ function M.yazi(config, input_path)
7373
yazi_event_handling.process_events_emitted_from_yazi(events)
7474

7575
local last_directory = event_info.last_directory
76+
7677
if last_directory == nil then
7778
if path:is_file() then
7879
last_directory = path:parent()
7980
else
8081
last_directory = path
8182
end
8283
end
84+
8385
utils.on_yazi_exited(prev_win, prev_buf, win, config, selected_files, {
84-
last_directory = event_info.last_directory or path:parent(),
86+
last_directory = last_directory,
8587
})
8688

8789
if hovered_url then

spec/yazi/helpers/test_files.lua

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
local M = {}
2+
3+
---@param target_file string
4+
function M.create_test_file(target_file)
5+
local plenary_path = require("plenary.path")
6+
local file = io.open(target_file, "w") -- Open or create the file in write mode
7+
assert(file, "Failed to create file " .. target_file)
8+
if file then
9+
file:write("")
10+
file:close()
11+
end
12+
assert(plenary_path:new(target_file):exists())
13+
assert(plenary_path:new(target_file):is_file())
14+
assert(plenary_path:new(target_file):parent():is_dir())
15+
end
16+
17+
return M

spec/yazi/yazi_spec.lua

+92-32
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local assert = require("luassert")
44
local mock = require("luassert.mock")
55
local match = require("luassert.match")
66
local spy = require("luassert.spy")
7+
local test_files = require("spec.yazi.helpers.test_files")
78
package.loaded["yazi.process.yazi_process"] =
89
require("spec.yazi.helpers.fake_yazi_process")
910
local fake_yazi_process = require("spec.yazi.helpers.fake_yazi_process")
@@ -68,38 +69,97 @@ describe("opening a file", function()
6869
assert_opened_yazi_with_files({ "/tmp/" })
6970
end)
7071

71-
it(
72-
"calls the yazi_closed_successfully hook when a file is selected in yazi's chooser",
73-
function()
74-
local target_file = "/abc/test-file-potato.txt"
75-
76-
fake_yazi_process.setup_created_instances_to_instantly_exit({
77-
selected_files = { target_file },
78-
})
79-
80-
---@param state YaziClosedState
81-
---@diagnostic disable-next-line: unused-local
82-
local spy_hook = spy.new(function(chosen_file, _config, state)
83-
assert.equals(target_file, chosen_file)
84-
assert.equals("/abc", state.last_directory.filename)
85-
end)
86-
87-
vim.api.nvim_command("edit /abc/test-file.txt")
88-
89-
plugin.yazi({
90-
chosen_file_path = "/tmp/yazi_filechosen",
91-
---@diagnostic disable-next-line: missing-fields
92-
hooks = {
93-
---@diagnostic disable-next-line: assign-type-mismatch
94-
yazi_closed_successfully = spy_hook,
95-
},
96-
})
97-
98-
assert
99-
.spy(spy_hook)
100-
.was_called_with(target_file, match.is_table(), match.is_table())
101-
end
102-
)
72+
describe("when a file is selected in yazi's chooser", function()
73+
it(
74+
"calls the yazi_closed_successfully hook with the target_file and last_directory",
75+
function()
76+
fake_yazi_process.setup_created_instances_to_instantly_exit({
77+
selected_files = {
78+
-- in this test, the cd event defines the last_directory so this is ignored
79+
},
80+
---@type YaziChangeDirectoryEvent[]
81+
events = {
82+
{
83+
type = "cd",
84+
timestamp = "123",
85+
id = "123",
86+
url = "/abc",
87+
},
88+
},
89+
})
90+
91+
---@param state YaziClosedState
92+
---@diagnostic disable-next-line: unused-local
93+
local spy_hook = spy.new(function(chosen_file, _config, state)
94+
assert.equals(nil, chosen_file)
95+
assert.equals("/abc", state.last_directory.filename)
96+
end)
97+
98+
plugin.yazi({
99+
chosen_file_path = "/tmp/yazi_filechosen",
100+
---@diagnostic disable-next-line: missing-fields
101+
hooks = {
102+
---@diagnostic disable-next-line: assign-type-mismatch
103+
yazi_closed_successfully = spy_hook,
104+
},
105+
})
106+
107+
assert
108+
.spy(spy_hook)
109+
.was_called_with(nil, match.is_table(), match.is_table())
110+
end
111+
)
112+
113+
it(
114+
"uses the parent directory of the input_path as the last_directory when no events are emitted",
115+
function()
116+
local plenary_path = require("plenary.path")
117+
-- it can happen that we don't know what the last_directory was when
118+
-- yazi has exited. This currently happens when `ya` is started too
119+
-- late - yazi has already reported its `cd` event before `ya` starts
120+
-- due to https://github.com/sxyazi/yazi/issues/1314
121+
--
122+
-- we work around this by using the parent directory of the input_path
123+
-- since it's a good guess
124+
local target_file =
125+
"/tmp/test-file-potato-ea7142f8-ac6d-4037-882c-7dbc4f7b6c65.txt"
126+
test_files.create_test_file(target_file)
127+
128+
fake_yazi_process.setup_created_instances_to_instantly_exit({
129+
selected_files = { target_file },
130+
events = {
131+
-- no events are emitted from yazi
132+
},
133+
})
134+
135+
local spy_yazi_closed_successfully = spy.new(
136+
---@param state YaziClosedState
137+
---@diagnostic disable-next-line: unused-local
138+
function(chosen_file, _config, state)
139+
assert.equals(target_file, chosen_file)
140+
assert.equals("/tmp", state.last_directory.filename)
141+
assert.equals(
142+
"/tmp",
143+
plenary_path:new(target_file):parent().filename
144+
)
145+
end
146+
)
147+
148+
plugin.yazi({
149+
chosen_file_path = "/tmp/yazi_filechosen",
150+
---@diagnostic disable-next-line: missing-fields
151+
hooks = {
152+
---@diagnostic disable-next-line: assign-type-mismatch
153+
yazi_closed_successfully = spy_yazi_closed_successfully,
154+
},
155+
}, target_file)
156+
157+
assert
158+
.spy(spy_yazi_closed_successfully)
159+
.was_called_with(target_file, match.is_table(), match.is_table())
160+
end
161+
)
162+
end)
103163

104164
it("calls the yazi_opened hook when yazi is opened", function()
105165
local spy_yazi_opened_hook = spy.new()

0 commit comments

Comments
 (0)