Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lua/flutter-tools.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ local function setup_commands()
-- Lists
command("FlutterDevices", devices.list_devices)
command("FlutterEmulators", devices.list_emulators)
command("FlutterEmulatorsAvds", devices.list_emulators_avds)
--- Outline
command("FlutterOutlineOpen", outline.open)
command("FlutterOutlineToggle", outline.toggle)
Expand Down
73 changes: 66 additions & 7 deletions lua/flutter-tools/devices.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ local DEVICE = 2

---@param result string[]
---@param type integer
local function get_devices(result, type)
---@param is_avds boolean
local function get_devices(result, type, is_avds)
local parse_avds = is_avds == true
local devices = {}
for _, line in pairs(result) do
local device = M.parse(line, type)
local device
if parse_avds then
device = M.parse_avds(line, type)
else
device = M.parse(line, type)
end
if device then
table.insert(devices, device)
if type == EMULATOR and device.system and device.system == "android" then
Expand All @@ -34,6 +41,24 @@ local function get_devices(result, type)
return devices
end

---@param line string
---@param device_type number
---@return Device?
function M.parse_avds(line, device_type)
local parts = vim.split(line, "•")
local name_index = 1
local id_index = 1
return {
name = vim.trim(parts[name_index]),
id = vim.trim(parts[id_index]),
platform = "Android",
system = "dunno",
-- platform = vim.trim(parts[3]),
-- system = vim.trim(parts[4]),
type = device_type,
}
end

---@param line string
---@param device_type number
---@return Device?
Expand All @@ -59,11 +84,12 @@ end
--- return the parsed list and the found devices if any
---@param result string[]
---@param device_type integer?
---@param is_avds boolean
---@return SelectionEntry[]
function M.to_selection_entries(result, device_type)
function M.to_selection_entries(result, device_type, is_avds)
if not result or #result < 1 then return {} end
if not device_type then device_type = DEVICE end
local devices = get_devices(result, device_type)
local devices = get_devices(result, device_type, is_avds)
if #devices == 0 then vim.tbl_map(function(item) return { text = item } end, result) end
return vim.tbl_map(function(device)
local has_platform = device.platform and device.platform ~= ""
Expand All @@ -86,6 +112,17 @@ function M.close_emulator()
if M.emulator_job then M.emulator_job:shutdown() end
end

---@param emulator table
function M.launch_emulator_avd(emulator)
if not emulator then return end
executable.emulator(function(cmd)
args = { "@" .. emulator.id, "-gpu", "host", "-accel", "on" }
if emulator.cold_boot then table.insert(args, "-no-snapshot-load") end
M.emulator_job = Job:new({ command = cmd, args = args })
M.emulator_job:after_success(vim.schedule_wrap(handle_launch))
M.emulator_job:start()
end)
end
---@param emulator table
function M.launch_emulator(emulator)
if not emulator then return end
Expand All @@ -99,17 +136,39 @@ function M.launch_emulator(emulator)
end

---@param result string[]
local function show_emulators(result)
local lines = M.to_selection_entries(result, EMULATOR)
---@param is_avds boolean
local function show_emulators(result, is_avds)
local lines = M.to_selection_entries(result, EMULATOR, is_avds)
if #lines > 0 then
local on_select
if is_avds then
on_select = function(emulator) M.launch_emulator_avd(emulator) end
else
on_select = function(emulator) M.launch_emulator(emulator) end
end
ui.select({
title = "Flutter emulators",
lines = lines,
on_select = function(emulator) M.launch_emulator(emulator) end,
on_select = on_select,
})
else
print("no emulators")
end
end

function M.list_emulators_avds()
executable.emulator(function(cmd)
local job = Job:new({ command = cmd, args = { "-list-avds" } })
job:after_success(vim.schedule_wrap(function(j) show_emulators(j:result(), true) end))
job:after_failure(
vim.schedule_wrap(
function(j) return ui.notify(utils.join(j:stderr_result()), ui.ERROR, { timeout = 5000 }) end
)
)
job:start()
end)
end

function M.list_emulators()
executable.flutter(function(cmd)
local job = Job:new({ command = cmd, args = { "emulators" } })
Expand Down
12 changes: 12 additions & 0 deletions lua/flutter-tools/executable.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ local Job = require("plenary.job")
---
--- True if fvm provides the Flutter SDK, otherwise nil or false.
---@field fvm boolean?
---@field emulator_bin string

---@private
---@class flutter.internal.Paths
Expand Down Expand Up @@ -83,6 +84,7 @@ local function get_default_binaries()
flutter_bin = flutter_bin,
dart_bin = fn.resolve(fn.exepath("dart")),
flutter_sdk = flutter_sdk_root(flutter_bin),
emulator_bin = fn.resolve(fn.exepath("emulator")),
}
end

Expand Down Expand Up @@ -151,6 +153,7 @@ function M.get(callback)
-- Provide default values to make the linter happy.
dart_sdk = "",
dart_bin = "",
emulator_bin = fn.exepath("emulator") or "",
}
cached_paths.dart_sdk = dart_sdk_root(cached_paths)
cached_paths.dart_bin = flutter_sdk_dart_bin(cached_paths.flutter_sdk)
Expand All @@ -166,6 +169,7 @@ function M.get(callback)
-- Provide default values to make the linter happy.
dart_sdk = "",
dart_bin = "",
emulator_bin = fn.exepath("emulator") or "",
}
cached_paths.dart_sdk = dart_sdk_root(cached_paths)
cached_paths.dart_bin = flutter_sdk_dart_bin(cached_paths.flutter_sdk)
Expand All @@ -179,6 +183,7 @@ function M.get(callback)
flutter_sdk = paths.flutter_sdk,
dart_bin = paths.dart_bin,
dart_sdk = dart_sdk_root(paths),
emulator_bin = fn.exepath("emulator") or "",
}
callback(paths)
end)
Expand All @@ -192,6 +197,7 @@ function M.get(callback)
flutter_sdk = internal_paths.flutter_sdk,
dart_bin = internal_paths.dart_bin,
dart_sdk = dart_sdk_root(internal_paths),
emulator_bin = fn.exepath("emulator") or "",
}
if cached_paths.flutter_sdk then
cached_paths.dart_bin = flutter_sdk_dart_bin(cached_paths.flutter_sdk)
Expand All @@ -208,6 +214,12 @@ function M.flutter(callback)
M.get(function(paths) callback(paths.flutter_bin) end)
end

--- Fetch the path to the users androidSdk -> emulator installation.
---@param callback fun(emulator_bin: string):nil
function M.emulator(callback)
M.get(function(paths) callback(paths.emulator_bin) end)
end

--- Fetch the path to the users dart installation.
---@param callback fun(dart_bin: string):nil
function M.dart(callback)
Expand Down
6 changes: 6 additions & 0 deletions lua/flutter-tools/menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ function M.commands(opts)
hint = "Show the available emulator devices",
command = require("flutter-tools.devices").list_emulators,
},
{
id = "flutter-tools-list-emulators-avd",
label = "List Emulator avds",
hint = "Show the available avds",
command = require("flutter-tools.devices").list_emulators_avds,
},
{
id = "flutter-tools-open-outline",
label = "Open Outline",
Expand Down