@@ -300,28 +300,41 @@ fn handle_split_window(args: SplitWindowArgs<'_>) -> Result<i32, ShimError> {
300300 ) ;
301301
302302 let sid = session_id ( ) ?;
303- let mut registry = state:: load ( & sid) ?;
303+ let mut locked = state:: load_and_lock ( & sid) ?;
304304
305305 // Determine which window the target pane belongs to
306306 let parent_pane_id = resolve_pane_id ( args. target ) ;
307- let window_id = registry
307+ let window_id = locked
308+ . registry ( )
308309 . panes
309310 . get ( & parent_pane_id)
310311 . map ( |p| p. window_id . clone ( ) )
311312 . unwrap_or_else ( || "0" . to_string ( ) ) ;
312313
313- let pane_id = create_pty_pane ( & mut registry, & window_id, & args. command ) ?;
314- state:: save ( & sid, & registry) ?;
314+ let pane_id = create_pty_pane ( locked. registry_mut ( ) , & window_id, & args. command ) ?;
315315
316- if args. print_info {
317- let fmt = args. format . unwrap_or ( "#{pane_id}" ) ;
318- let session_name = & registry. session_name ;
319- let window_name = registry
316+ // Capture format values before save consumes the guard (only when needed)
317+ let print_values = if args. print_info {
318+ let session_name = locked. registry ( ) . session_name . clone ( ) ;
319+ let window_name = locked
320+ . registry ( )
320321 . windows
321322 . get ( & window_id)
322- . map ( |w| w. name . as_str ( ) )
323- . unwrap_or ( "main" ) ;
324- let output = expand_format ( fmt, & pane_id, session_name, & window_id, window_name, "" ) ;
323+ . map ( |w| w. name . clone ( ) )
324+ . unwrap_or_else ( || "main" . to_string ( ) ) ;
325+ Some ( (
326+ args. format . unwrap_or ( "#{pane_id}" ) ,
327+ session_name,
328+ window_name,
329+ ) )
330+ } else {
331+ None
332+ } ;
333+
334+ locked. save ( ) ?;
335+
336+ if let Some ( ( fmt, session_name, window_name) ) = print_values {
337+ let output = expand_format ( fmt, & pane_id, & session_name, & window_id, & window_name, "" ) ;
325338 println ! ( "{}" , output) ;
326339 }
327340
@@ -451,10 +464,11 @@ fn handle_kill_pane(args: KillPaneArgs<'_>) -> Result<i32, ShimError> {
451464 debug ! ( event = "shim.kill_pane_started" , target = ?args. target) ;
452465
453466 let sid = session_id ( ) ?;
454- let mut registry = state:: load ( & sid) ?;
467+ let mut locked = state:: load_and_lock ( & sid) ?;
455468
456469 let pane_id = resolve_pane_id ( args. target ) ;
457- let pane = registry
470+ let pane = locked
471+ . registry ( )
458472 . panes
459473 . get ( & pane_id)
460474 . ok_or_else ( || ShimError :: state ( format ! ( "pane {} not found in registry" , pane_id) ) ) ?;
@@ -492,8 +506,8 @@ fn handle_kill_pane(args: KillPaneArgs<'_>) -> Result<i32, ShimError> {
492506 }
493507 }
494508
495- registry . remove_pane ( & pane_id) ;
496- state :: save ( & sid , & registry ) ?;
509+ locked . registry_mut ( ) . remove_pane ( & pane_id) ;
510+ locked . save ( ) ?;
497511
498512 debug ! ( event = "shim.kill_pane_completed" , pane_id = pane_id) ;
499513 Ok ( 0 )
@@ -574,17 +588,17 @@ fn handle_select_pane(args: SelectPaneArgs<'_>) -> Result<i32, ShimError> {
574588 // Only need state if we have style or title to store
575589 if args. style . is_some ( ) || args. title . is_some ( ) {
576590 let sid = session_id ( ) ?;
577- let mut registry = state:: load ( & sid) ?;
591+ let mut locked = state:: load_and_lock ( & sid) ?;
578592 let pane_id = resolve_pane_id ( args. target ) ;
579593
580- if let Some ( pane) = registry . panes . get_mut ( & pane_id) {
594+ if let Some ( pane) = locked . registry_mut ( ) . panes . get_mut ( & pane_id) {
581595 if let Some ( style) = args. style {
582596 pane. border_style = style. to_string ( ) ;
583597 }
584598 if let Some ( title) = args. title {
585599 pane. title = title. to_string ( ) ;
586600 }
587- state :: save ( & sid , & registry ) ?;
601+ locked . save ( ) ?;
588602 }
589603 }
590604
@@ -604,15 +618,15 @@ fn handle_set_option(args: SetOptionArgs<'_>) -> Result<i32, ShimError> {
604618 // Store pane-scoped options in the pane entry
605619 if matches ! ( args. scope, OptionScope :: Pane ) {
606620 let sid = session_id ( ) ?;
607- let mut registry = state:: load ( & sid) ?;
621+ let mut locked = state:: load_and_lock ( & sid) ?;
608622 let pane_id = resolve_pane_id ( args. target ) ;
609623
610- if let Some ( pane) = registry . panes . get_mut ( & pane_id) {
624+ if let Some ( pane) = locked . registry_mut ( ) . panes . get_mut ( & pane_id) {
611625 // Store known pane options
612626 if args. key == "pane-border-style" || args. key . ends_with ( "-style" ) {
613627 pane. border_style = args. value ;
614628 }
615- state :: save ( & sid , & registry ) ?;
629+ locked . save ( ) ?;
616630 }
617631 }
618632
@@ -655,21 +669,21 @@ fn handle_new_session(args: NewSessionArgs<'_>) -> Result<i32, ShimError> {
655669 debug ! ( event = "shim.new_session_started" , name = ?args. session_name) ;
656670
657671 let sid = session_id ( ) ?;
658- let mut registry = state:: load ( & sid) ?;
672+ let mut locked = state:: load_and_lock ( & sid) ?;
659673
674+ // Read phase: derive names and IDs from current state
660675 let session_name = args
661676 . session_name
662677 . map ( |s| s. to_string ( ) )
663- . unwrap_or_else ( || format ! ( "kild_{}" , registry. sessions. len( ) ) ) ;
664-
678+ . unwrap_or_else ( || format ! ( "kild_{}" , locked. registry( ) . sessions. len( ) ) ) ;
665679 let window_name = args
666680 . window_name
667681 . map ( |s| s. to_string ( ) )
668682 . unwrap_or_else ( || "main" . to_string ( ) ) ;
683+ let window_id = format ! ( "{}" , locked. registry( ) . windows. len( ) ) ;
669684
670- // Allocate a new window
671- let window_id = format ! ( "{}" , registry. windows. len( ) ) ;
672- registry. windows . insert (
685+ // Write phase: mutate registry
686+ locked. registry_mut ( ) . windows . insert (
673687 window_id. clone ( ) ,
674688 WindowEntry {
675689 name : window_name,
@@ -678,18 +692,18 @@ fn handle_new_session(args: NewSessionArgs<'_>) -> Result<i32, ShimError> {
678692 ) ;
679693
680694 // Create initial pane in the new window
681- let pane_id = create_pty_pane ( & mut registry , & window_id, & [ ] ) ?;
695+ let pane_id = create_pty_pane ( locked . registry_mut ( ) , & window_id, & [ ] ) ?;
682696
683697 // Register session
684- registry . sessions . insert (
698+ locked . registry_mut ( ) . sessions . insert (
685699 session_name. clone ( ) ,
686700 SessionEntry {
687701 name : session_name. clone ( ) ,
688702 windows : vec ! [ window_id] ,
689703 } ,
690704 ) ;
691705
692- state :: save ( & sid , & registry ) ?;
706+ locked . save ( ) ?;
693707
694708 if args. print_info {
695709 let fmt = args. format . unwrap_or ( "#{pane_id}" ) ;
@@ -708,36 +722,37 @@ fn handle_new_window(args: NewWindowArgs<'_>) -> Result<i32, ShimError> {
708722 debug ! ( event = "shim.new_window_started" , name = ?args. name) ;
709723
710724 let sid = session_id ( ) ?;
711- let mut registry = state:: load ( & sid) ?;
725+ let mut locked = state:: load_and_lock ( & sid) ?;
712726
713727 let window_name = args
714728 . name
715729 . map ( |s| s. to_string ( ) )
716730 . unwrap_or_else ( || "window" . to_string ( ) ) ;
717- let window_id = format ! ( "{}" , registry. windows. len( ) ) ;
718731
719- registry. windows . insert (
732+ // Read phase: derive IDs from current state
733+ let window_id = format ! ( "{}" , locked. registry( ) . windows. len( ) ) ;
734+ let session_key = args
735+ . target
736+ . and_then ( |t| t. split ( ':' ) . next ( ) )
737+ . unwrap_or ( & locked. registry ( ) . session_name )
738+ . to_string ( ) ;
739+
740+ // Write phase: mutate registry
741+ locked. registry_mut ( ) . windows . insert (
720742 window_id. clone ( ) ,
721743 WindowEntry {
722744 name : window_name. clone ( ) ,
723745 pane_ids : vec ! [ ] ,
724746 } ,
725747 ) ;
726748
727- let pane_id = create_pty_pane ( & mut registry, & window_id, & [ ] ) ?;
728-
729- // Add window to the target session (or default session)
730- let session_key = args
731- . target
732- . and_then ( |t| t. split ( ':' ) . next ( ) )
733- . unwrap_or ( & registry. session_name )
734- . to_string ( ) ;
749+ let pane_id = create_pty_pane ( locked. registry_mut ( ) , & window_id, & [ ] ) ?;
735750
736- if let Some ( session) = registry . sessions . get_mut ( & session_key) {
751+ if let Some ( session) = locked . registry_mut ( ) . sessions . get_mut ( & session_key) {
737752 session. windows . push ( window_id. clone ( ) ) ;
738753 }
739754
740- state :: save ( & sid , & registry ) ?;
755+ locked . save ( ) ?;
741756
742757 if args. print_info {
743758 let fmt = args. format . unwrap_or ( "#{pane_id}" ) ;
@@ -789,13 +804,13 @@ fn handle_break_pane(args: BreakPaneArgs<'_>) -> Result<i32, ShimError> {
789804 debug ! ( event = "shim.break_pane_started" , source = ?args. source) ;
790805
791806 let sid = session_id ( ) ?;
792- let mut registry = state:: load ( & sid) ?;
807+ let mut locked = state:: load_and_lock ( & sid) ?;
793808
794809 let pane_id = resolve_pane_id ( args. source ) ;
795- if let Some ( pane) = registry . panes . get_mut ( & pane_id) {
810+ if let Some ( pane) = locked . registry_mut ( ) . panes . get_mut ( & pane_id) {
796811 pane. hidden = true ;
797812 }
798- state :: save ( & sid , & registry ) ?;
813+ locked . save ( ) ?;
799814
800815 debug ! ( event = "shim.break_pane_completed" , pane_id = pane_id) ;
801816 Ok ( 0 )
@@ -805,13 +820,13 @@ fn handle_join_pane(args: JoinPaneArgs<'_>) -> Result<i32, ShimError> {
805820 debug ! ( event = "shim.join_pane_started" , source = ?args. source) ;
806821
807822 let sid = session_id ( ) ?;
808- let mut registry = state:: load ( & sid) ?;
823+ let mut locked = state:: load_and_lock ( & sid) ?;
809824
810825 let pane_id = resolve_pane_id ( args. source ) ;
811- if let Some ( pane) = registry . panes . get_mut ( & pane_id) {
826+ if let Some ( pane) = locked . registry_mut ( ) . panes . get_mut ( & pane_id) {
812827 pane. hidden = false ;
813828 }
814- state :: save ( & sid , & registry ) ?;
829+ locked . save ( ) ?;
815830
816831 debug ! ( event = "shim.join_pane_completed" , pane_id = pane_id) ;
817832 Ok ( 0 )
0 commit comments