Skip to content

Commit

Permalink
fix: can view drives on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Nov 5, 2023
1 parent 7ea4dda commit 126a8a2
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 43 deletions.
104 changes: 80 additions & 24 deletions lua/oil/adapters/files.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ local fs_stat_meta_fields = {
stat = function(parent_url, entry, cb)
local _, path = util.parse_url(parent_url)
assert(path)
local dir = fs.posix_to_os_path(path)
uv.fs_stat(fs.join(dir, entry[FIELD_NAME]), cb)
local dir = fs.posix_to_os_path(path .. entry[FIELD_NAME])
uv.fs_stat(dir, cb)
end,
}

Expand Down Expand Up @@ -208,6 +208,9 @@ end
M.normalize_url = function(url, callback)
local scheme, path = util.parse_url(url)
assert(path)
if fs.is_windows and path == '/' then
return callback(url)
end
local os_path = vim.fn.fnamemodify(fs.posix_to_os_path(path), ":p")
uv.fs_realpath(os_path, function(err, new_os_path)
local realpath = new_os_path or os_path
Expand Down Expand Up @@ -254,12 +257,66 @@ M.get_entry_path = function(url, entry, cb)
end
end

---@param url string
---@param column_defs string[]
---@param cb fun(err?: string, entries?: oil.InternalEntry[], fetch_more?: fun())
local function list_windows_drives(url, column_defs, cb)
local fetch_meta = columns.get_metadata_fetcher(M, column_defs)
local stdout = ""
local jid = vim.fn.jobstart({ 'wmic', 'logicaldisk', 'get', 'name' }, {
stdout_buffered = true,
on_stdout = function(_, data)
stdout = table.concat(data, '\n')
end,
on_exit = function(_, code)
if code ~= 0 then
return cb("Error listing windows devices")
end
local lines = vim.split(stdout, '\n', { plain = true, trimempty = true })
-- Remove the "Name" header
table.remove(lines, 1)
local internal_entries = {}
local complete_disk_cb = util.cb_collect(#lines, function(err)
if err then
cb(err)
else
cb(nil, internal_entries)
end
end)

for _, disk in ipairs(lines) do
if disk:match("^%s*$") then
-- Skip empty line
complete_disk_cb()
else
disk = disk:gsub(":%s*$", "")
local cache_entry = cache.create_entry(url, disk, "directory")
fetch_meta(url, cache_entry, function(err)
if err then
complete_disk_cb(err)
else
table.insert(internal_entries, cache_entry)
complete_disk_cb()
end
end)
end
end
end
})
if jid <= 0 then
cb("Could not list windows devices")
end
end

---@param url string
---@param column_defs string[]
---@param cb fun(err?: string, entries?: oil.InternalEntry[], fetch_more?: fun())
M.list = function(url, column_defs, cb)
local _, path = util.parse_url(url)
assert(path)
if fs.is_windows and path == '/' then
return list_windows_drives(url, column_defs, cb)
end
local dir = fs.posix_to_os_path(path)
local fetch_meta = columns.get_metadata_fetcher(M, column_defs)

Expand Down Expand Up @@ -294,29 +351,25 @@ M.list = function(url, column_defs, cb)
for _, entry in ipairs(entries) do
local cache_entry = cache.create_entry(url, entry.name, entry.type)
fetch_meta(url, cache_entry, function(meta_err)
if err then
poll(meta_err)
else
table.insert(internal_entries, cache_entry)
local meta = cache_entry[FIELD_META]
-- Make sure we always get fs_stat info for links
if entry.type == "link" then
read_link_data(fs.join(dir, entry.name), function(link_err, link, link_stat)
if link_err then
poll(link_err)
else
if not meta then
meta = {}
cache_entry[FIELD_META] = meta
end
meta.link = link
meta.link_stat = link_stat
poll()
table.insert(internal_entries, cache_entry)
local meta = cache_entry[FIELD_META]
-- Make sure we always get fs_stat info for links
if entry.type == "link" then
read_link_data(fs.join(dir, entry.name), function(link_err, link, link_stat)
if link_err then
poll(link_err)
else
if not meta then
meta = {}
cache_entry[FIELD_META] = meta
end
end)
else
poll()
end
meta.link = link
meta.link_stat = link_stat
poll()
end
end)
else
poll()
end
end)
end
Expand All @@ -342,6 +395,9 @@ M.is_modifiable = function(bufnr)
local bufname = vim.api.nvim_buf_get_name(bufnr)
local _, path = util.parse_url(bufname)
assert(path)
if fs.is_windows and path == '/' then
return false
end
local dir = fs.posix_to_os_path(path)
local stat = uv.fs_stat(dir)
if not stat then
Expand Down
3 changes: 2 additions & 1 deletion lua/oil/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ end
M.posix_to_os_path = function(path)
if M.is_windows then
if vim.startswith(path, "/") then
local drive, rem = path:match("^/([^/]+)/(.*)$")
local drive = path:match("^/(%a+)")
local rem = path:sub(drive:len() + 2)
return string.format("%s:\\%s", drive, rem:gsub("/", "\\"))
else
local newpath = path:gsub("/", "\\")
Expand Down
20 changes: 10 additions & 10 deletions lua/oil/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -533,12 +533,12 @@ M.select = function(opts, callback)
local child = dir .. entry.name
local url = scheme .. child
local is_directory = entry.type == "directory"
or (
entry.type == "link"
and entry.meta
and entry.meta.link_stat
and entry.meta.link_stat.type == "directory"
)
or (
entry.type == "link"
and entry.meta
and entry.meta.link_stat
and entry.meta.link_stat.type == "directory"
)
if is_directory then
url = url .. "/"
-- If this is a new directory BUT we think we already have an entry with this name, disallow
Expand Down Expand Up @@ -623,9 +623,9 @@ M.select = function(opts, callback)
return finish(err)
end
if
opts.close
and vim.api.nvim_win_is_valid(prev_win)
and prev_win ~= vim.api.nvim_get_current_win()
opts.close
and vim.api.nvim_win_is_valid(prev_win)
and prev_win ~= vim.api.nvim_get_current_win()
then
vim.api.nvim_win_call(prev_win, function()
M.close()
Expand Down Expand Up @@ -758,7 +758,7 @@ local function restore_alt_buf()
-- If we are editing the same buffer that we started oil from, set the alternate to be
-- what it was before we opened oil
local has_orig_alt, alt_buffer =
pcall(vim.api.nvim_win_get_var, 0, "oil_original_alternate")
pcall(vim.api.nvim_win_get_var, 0, "oil_original_alternate")
if has_orig_alt and vim.api.nvim_buf_is_valid(alt_buffer) then
vim.fn.setreg("#", alt_buffer)
end
Expand Down
8 changes: 0 additions & 8 deletions lua/oil/pathutil.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
local fs = require("oil.fs")
local M = {}

---@param path string
---@return string
M.parent = function(path)
-- Do I love this hack? No I do not.
-- Does it work? Yes. Mostly. For now.
if fs.is_windows then
if path:match("^/%a+/?$") then
return path
end
end
if path == "/" then
return "/"
elseif path == "" then
Expand Down

0 comments on commit 126a8a2

Please sign in to comment.