authored by
Asherah Connor
<ashe@kivikakk.ee>
2 months ago
committed by Asherah Connor <ashe@kivikakk.ee> 2 months ago
committed by Asherah Connor <ashe@kivikakk.ee> 2 months ago
apps/liia/lib/liia/workspace.ex
| 38 +++++++++++++++--------
apps/liia/lib/liia/workspace_manager.ex
| 17 ++++++++--
apps/niia/lib/niia/connectivity.ex
| 7 ++--
apps/niia/lib/niia/window.ex
| 56 +++++++++++++++++++++++-----------
5 files changed, 86 insertions(+), 34 deletions(-)
diff --git a/apps/liia/lib/liia/application.ex b/apps/liia/lib/liia/application.ex
index 5c92f99..8be5087 100644
--- a/apps/liia/lib/liia/application.ex
+++ b/apps/liia/lib/liia/application.ex
@@ -6,6 +6,8 @@ defmodule Liia.Application do
@impl true
def start(_type, _args) do
children = [
+ {DynamicSupervisor,
+ name: Liia.WorkspaceSupervisor, strategy: :one_for_one, max_restarts: 0},
Liia.WorkspaceManager
]
diff --git a/apps/liia/lib/liia/workspace.ex b/apps/liia/lib/liia/workspace.ex
index 65f3a5e..397f733 100644
--- a/apps/liia/lib/liia/workspace.ex
+++ b/apps/liia/lib/liia/workspace.ex
@@ -2,16 +2,21 @@ defmodule Liia.Workspace do
use GenServer
require Logger
- def start_link(origin) do
- GenServer.start_link(__MODULE__, origin)
+ def start_link({origin, path}) do
+ GenServer.start_link(__MODULE__, {origin, path})
end
+ @type state() :: %{
+ origin: pid(),
+ path: String.t(),
+ niia_monitor: reference()
+ }
+
@impl true
- @spec init(pid()) :: any()
- def init(from) do
- Logger.debug("starting for #{inspect(node(from))}")
- niia_monitor = Process.monitor(from)
- {:ok, %{from: from, niia_monitor: niia_monitor}}
+ def init({origin, path}) do
+ Logger.debug("starting for #{inspect(node(origin))} in #{path}")
+ niia_monitor = Process.monitor(origin)
+ {:ok, %{origin: origin, path: path, niia_monitor: niia_monitor}}
end
@impl true
@@ -24,11 +29,20 @@ defmodule Liia.Workspace do
end
@impl true
- def terminate(reason, state) do
- Logger.debug(
- "reason #{inspect(reason)} with state #{inspect(state)}"
- )
+ def handle_call(:pwd, _from, %{path: path} = state) do
+ files =
+ [".." | File.ls!(path)]
+ |> Enum.sort()
+ |> Enum.map(&{&1, File.stat!(" " <> &1)})
+ |> Enum.sort_by(fn {_path, stat} -> stat.type != :directory end)
+ |> Enum.map(fn {path, stat} ->
+ if stat.type == :directory, do: "#{path}/", else: path
+ end)
- :ok
+ {:reply, {path, files}, state}
end
+
+ @impl true
+ def terminate(_reason, _state),
+ do: :ok
end
diff --git a/apps/liia/lib/liia/workspace_manager.ex b/apps/liia/lib/liia/workspace_manager.ex
index aaf423f..87a03b3 100644
--- a/apps/liia/lib/liia/workspace_manager.ex
+++ b/apps/liia/lib/liia/workspace_manager.ex
@@ -13,13 +13,26 @@ defmodule Liia.WorkspaceManager do
end
@impl true
- def handle_call(:create, {from, _tag}, state) do
- {:ok, ws_pid} = Liia.Workspace.start_link(from)
+ def handle_call({:create, path}, {from, _tag}, state) do
+ {:ok, ws_pid} =
+ DynamicSupervisor.start_child(
+ Liia.WorkspaceSupervisor,
+ {Liia.Workspace, {from, path}}
+ )
{:reply, ws_pid, state}
end
@impl true
+ def handle_info(msg, state) do
+ case msg do
+ {:DOWN, ref, :process, _, reason} ->
+ Logger.debug("linked ws? #{inspect(ref)} down: #{inspect(reason)}")
+ {:noreply, state}
+ end
+ end
+
+ @impl true
def terminate(reason, state) do
Logger.error("terminating for #{inspect(reason)} with state #{inspect(state)}")
:ok
diff --git a/apps/niia/lib/niia/connectivity.ex b/apps/niia/lib/niia/connectivity.ex
index 9612d42..a483409 100644
--- a/apps/niia/lib/niia/connectivity.ex
+++ b/apps/niia/lib/niia/connectivity.ex
@@ -12,12 +12,15 @@ defmodule Niia.Connectivity do
true = Node.connect(liia_node)
:global.sync()
- ws_pid = GenServer.call({:global, Liia.WorkspaceManager}, :create)
+ # This will not work if cwd doesn't exist on liia.
+ ws_pid = GenServer.call({:global, Liia.WorkspaceManager}, {:create, File.cwd!()})
Logger.debug("connected to #{inspect(ws_pid)}")
-
Niia.Window.set_title("Niia (#{liia_node}:#{inspect(ws_pid)})")
+ {pwd, files} = GenServer.call(ws_pid, :pwd)
+ Niia.Window.set_pwd(pwd, files)
+
{:ok, ws_pid}
end
end
diff --git a/apps/niia/lib/niia/window.ex b/apps/niia/lib/niia/window.ex
index 80ca98c..2c0a828 100644
--- a/apps/niia/lib/niia/window.ex
+++ b/apps/niia/lib/niia/window.ex
@@ -5,30 +5,50 @@ defmodule Niia.Window do
alias WxEx.Constants.WxWidgets
import WxEx.Records
- def start_link([]) do
- GenServer.start_link(__MODULE__, nil, name: __MODULE__)
- end
+ def start_link([]),
+ do: GenServer.start_link(__MODULE__, nil, name: __MODULE__)
- def set_title(msg) do
- GenServer.cast(__MODULE__, {:set_title, msg})
- end
+ def set_title(msg),
+ do: GenServer.cast(__MODULE__, {:set_title, msg})
+
+ def set_pwd(pwd, files),
+ do: GenServer.cast(__MODULE__, {:set_pwd, pwd, files})
+
+ @type state() :: %{
+ wx: :wx.wx_object(),
+ els: els()
+ }
+
+ @type els() :: %{
+ frame: :wxFrame.wxFrame(),
+ pwd_text: :wxStaticText.wxStaticText(),
+ file_list: :wxListBox.wxListBox()
+ }
@impl true
def init(nil) do
wx = :wx.new()
- {frame, text_ctrl} = :wx.batch(fn -> create_window(wx) end)
- :wxWindow.show(frame)
- {:ok, %{wx: wx, frame: frame, text_ctrl: text_ctrl}}
+ els = :wx.batch(fn -> create_window(wx) end)
+ {:ok, %{wx: wx, els: els}}
end
@impl true
- def handle_cast({:set_title, title}, %{frame: frame} = state) do
+ def handle_cast({:set_title, title}, %{els: %{frame: frame}} = state) do
:wxFrame.setTitle(frame, title)
{:noreply, state}
end
+ def handle_cast(
+ {:set_pwd, pwd, files},
+ %{els: %{pwd_text: pwd_text, file_list: file_list}} = state
+ ) do
+ :wxStaticText.setLabel(pwd_text, pwd)
+ :wxListBox.set(file_list, files)
+ {:noreply, state}
+ end
+
@impl true
- def handle_info(msg, %{frame: frame} = state) do
+ def handle_info(msg, %{els: %{frame: frame}} = state) do
case msg do
wx(event: wxClose()) ->
:wxFrame.destroy(frame)
@@ -52,6 +72,7 @@ defmodule Niia.Window do
:ok
end
+ @spec create_window(:wx.wx_object()) :: els()
defp create_window(wx) do
frame = :wxFrame.new(wx, -1, "HELLO", size: {600, 400})
@@ -67,14 +88,11 @@ defmodule Niia.Window do
activity_pane_sizer = :wxBoxSizer.new(WxWidgets.wxVERTICAL())
:wxWindow.setSizer(activity_pane, activity_pane_sizer)
- text = :wxStaticText.new(activity_pane, -1, "Henlo")
- :wxSizer.add(activity_pane_sizer, text)
+ pwd_text = :wxStaticText.new(activity_pane, -1, "Henlo")
+ :wxSizer.add(activity_pane_sizer, pwd_text)
file_list =
- :wxListBox.new(activity_pane, -1,
- choices: ["a", "b", "c"],
- style: WxWidgets.wxLB_SINGLE()
- )
+ :wxListBox.new(activity_pane, -1, style: WxWidgets.wxLB_SINGLE())
:wxSizer.add(activity_pane_sizer, file_list, proportion: 1, flag: WxWidgets.wxGROW())
@@ -82,6 +100,8 @@ defmodule Niia.Window do
true = :wxSplitterWindow.splitVertically(splitter, activity_pane, text_ctrl)
- {frame, text_ctrl}
+ :wxWindow.show(frame)
+
+ %{frame: frame, pwd_text: pwd_text, file_list: file_list}
end
end