aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Letan <lthms@soap.coffee>2022-08-31 18:34:06 +0200
committerThomas Letan <lthms@soap.coffee>2022-08-31 18:34:06 +0200
commit88dd944b2e9a252470589d5092372a9493f38a10 (patch)
tree3e70a984dbf8edc5e08cd9797018d034ac895e71
parentForce to build in release mode (diff)
Add the 'Get_workspaces' command
-rw-r--r--bin/spatial/state.ml15
-rw-r--r--bin/spatial/workspaces_registry.ml12
-rw-r--r--bin/spatialmsg/main.ml45
-rw-r--r--lib/spatial_ipc/spatial_ipc.ml17
-rw-r--r--lib/spatial_ipc/spatial_ipc.mli2
5 files changed, 84 insertions, 7 deletions
diff --git a/bin/spatial/state.ml b/bin/spatial/state.ml
index 2b4f994..557f327 100644
--- a/bin/spatial/state.ml
+++ b/bin/spatial/state.ml
@@ -193,6 +193,21 @@ let client_command_handle :
None )
in
(res, { success = true })
+ | Get_workspaces ->
+ let current, state =
+ match int_of_string_opt state.current_workspace with
+ | Some current -> (current, state)
+ | None ->
+ (* Forcing a valid workspace *)
+ (* TODO: Force a jump to this workspace *)
+ (0, { state with current_workspace = "0" })
+ in
+ let windows =
+ Workspaces_registry.summary state.workspaces
+ |> List.map (fun (k, w) ->
+ (k, (Windows_registry.find w state.windows).app_id))
+ in
+ ((state, false, None), { current; windows })
| Get_windows -> (
let ribbon =
Workspaces_registry.find_opt state.current_workspace state.workspaces
diff --git a/bin/spatial/workspaces_registry.ml b/bin/spatial/workspaces_registry.ml
index 5e8c94d..fc71b1e 100644
--- a/bin/spatial/workspaces_registry.ml
+++ b/bin/spatial/workspaces_registry.ml
@@ -16,6 +16,18 @@ let register_window default_full_view default_maximum_visible workspace window
Some (Ribbon.insert_window window ribbon))
reg
+let summary (reg : t) =
+ Seq.filter_map
+ (fun (key, ribbon) ->
+ match int_of_string_opt key with
+ | Some k when 0 <= k -> (
+ match ribbon.Ribbon.visible with
+ | Some (f, l) -> Some (k, List.nth l f)
+ | _ -> None)
+ | _ -> None)
+ (Map.to_seq reg)
+ |> List.of_seq
+
let unregister = Map.remove
let find = Map.find
let find_opt = Map.find_opt
diff --git a/bin/spatialmsg/main.ml b/bin/spatialmsg/main.ml
index 057b536..2000365 100644
--- a/bin/spatialmsg/main.ml
+++ b/bin/spatialmsg/main.ml
@@ -1,5 +1,20 @@
open Spatial_ipc
+let default_icon = ""
+let empty_workspace_icon = "◯"
+
+let icon_of = function
+ | "firefox" -> Some ""
+ | "kitty" -> Some ""
+ | "Slack" -> Some ""
+ | "emacs" -> Some ""
+ | _ -> None
+
+let workspace_icon workspace windows =
+ List.assq_opt workspace windows |> function
+ | Some app_id -> Option.value ~default:default_icon (icon_of app_id)
+ | None -> empty_workspace_icon
+
let () =
Clap.description "A client to communicate with a Spatial instance.";
@@ -23,12 +38,9 @@ let () =
| Some idx, Some focus when idx < List.length reply.windows ->
let tooltip = List.nth reply.windows idx in
let name =
- match tooltip with
- | "firefox" -> ""
- | "kitty" -> ""
- | "Slack" -> ""
- | "emacs" -> ""
- | _ -> " " ^ tooltip
+ Option.value
+ ~default:(default_icon ^ " " ^ tooltip)
+ (icon_of tooltip)
in
let cls = if idx = focus then "focus" else "unfocus" in
Format.(printf "%s\n%s\n%s" name tooltip cls)
@@ -39,4 +51,25 @@ let () =
let marker = if reply.focus = Some idx then "*" else "" in
Format.printf "| %s%s%s | " marker name marker)
reply.windows)
+ | "get_workspaces" -> (
+ let cmd = Clap.optional_int ~placeholder:"INDEX" () in
+ Clap.close ();
+
+ let reply = send_command Get_workspaces in
+
+ match cmd with
+ | Some i ->
+ let cls = if i = reply.current then "focus" else "unfocused" in
+ Format.(
+ printf "%s\n%s\n%s"
+ (workspace_icon i reply.windows)
+ (string_of_int i) cls)
+ | None ->
+ Format.(
+ printf "%a@?"
+ (pp_print_list
+ ~pp_sep:(fun fmt () -> pp_print_string fmt " ")
+ (fun fmt k ->
+ Format.printf "%d:%s" k (workspace_icon k reply.windows)))
+ (List.init 6 (fun x -> x + 1))))
| _ -> exit 2
diff --git a/lib/spatial_ipc/spatial_ipc.ml b/lib/spatial_ipc/spatial_ipc.ml
index a574fc1..d523680 100644
--- a/lib/spatial_ipc/spatial_ipc.ml
+++ b/lib/spatial_ipc/spatial_ipc.ml
@@ -101,13 +101,24 @@ let get_windows_reply_encoding : get_windows_reply Data_encoding.t =
(fun (focus, windows) -> { focus; windows })
(obj2 (opt "focus" int31) (req "windows" @@ list string))
+type get_workspaces_reply = { current : int; windows : (int * string) list }
+
+let get_workspaces_reply_encoding : get_workspaces_reply Data_encoding.t =
+ let open Data_encoding in
+ conv
+ (fun { current; windows } -> (current, windows))
+ (fun (current, windows) -> { current; windows })
+ (obj2 (req "current" int31) (req "windows" @@ list (tup2 int31 string)))
+
type 'a t =
| Run_command : command -> run_command_reply t
| Get_windows : get_windows_reply t
+ | Get_workspaces : get_workspaces_reply t
let reply_encoding : type a. a t -> a Data_encoding.t = function
| Run_command _ -> run_command_reply_encoding
| Get_windows -> get_windows_reply_encoding
+ | Get_workspaces -> get_workspaces_reply_encoding
let reply_to_string : type a. a t -> a -> string =
fun cmd reply ->
@@ -125,11 +136,14 @@ let reply_of_string : type a. a t -> string -> a option =
let reply_of_string_exn cmd reply =
match reply_of_string cmd reply with
| Some x -> x
- | None -> failwith "cannot parse reply"
+ | None ->
+ Format.printf "%S\n" reply;
+ failwith "cannot parse reply"
let to_raw_message : type a. a t -> Raw_message.t = function
| Run_command cmd -> (0l, command_to_string cmd)
| Get_windows -> (1l, "")
+ | Get_workspaces -> (2l, "")
type packed = Packed : 'a t -> packed
@@ -137,6 +151,7 @@ let of_raw_message (op, payload) =
match op with
| 0l -> (fun x -> Packed (Run_command x)) <$> command_of_string payload
| 1l -> Some (Packed Get_windows)
+ | 2l -> Some (Packed Get_workspaces)
| _ -> None
type socket = Socket.socket
diff --git a/lib/spatial_ipc/spatial_ipc.mli b/lib/spatial_ipc/spatial_ipc.mli
index 6a00c14..c2af336 100644
--- a/lib/spatial_ipc/spatial_ipc.mli
+++ b/lib/spatial_ipc/spatial_ipc.mli
@@ -28,10 +28,12 @@ val command_of_string_exn : string -> command
type run_command_reply = { success : bool }
type get_windows_reply = { focus : int option; windows : string list }
+type get_workspaces_reply = { current : int; windows : (int * string) list }
type 'a t =
| Run_command : command -> run_command_reply t
| Get_windows : get_windows_reply t
+ | Get_workspaces : get_workspaces_reply t
type socket = Unix.file_descr