diff options
author | Thomas Letan <lthms@soap.coffee> | 2022-08-31 18:34:06 +0200 |
---|---|---|
committer | Thomas Letan <lthms@soap.coffee> | 2022-08-31 18:34:06 +0200 |
commit | 88dd944b2e9a252470589d5092372a9493f38a10 (patch) | |
tree | 3e70a984dbf8edc5e08cd9797018d034ac895e71 | |
parent | Force to build in release mode (diff) |
Add the 'Get_workspaces' command
-rw-r--r-- | bin/spatial/state.ml | 15 | ||||
-rw-r--r-- | bin/spatial/workspaces_registry.ml | 12 | ||||
-rw-r--r-- | bin/spatialmsg/main.ml | 45 | ||||
-rw-r--r-- | lib/spatial_ipc/spatial_ipc.ml | 17 | ||||
-rw-r--r-- | lib/spatial_ipc/spatial_ipc.mli | 2 |
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 |