]> jxnshi.xyz Git - mesange.git/commitdiff
Working on room
authorjxnshi <jxnshi@cock.li>
Fri, 17 Jan 2025 13:18:26 +0000 (14:18 +0100)
committerjxnshi <jxnshi@cock.li>
Fri, 17 Jan 2025 13:18:26 +0000 (14:18 +0100)
client-cli/client-cli
client-cli/command.odin
client-cli/main.odin
client-cli/state.odin
server/server

index 63faac56ca9366faace229754610c73b165e839a..f8e03945b4fe42385a1d46a04e55317468e01c92 100755 (executable)
Binary files a/client-cli/client-cli and b/client-cli/client-cli differ
index d3bc000db17896a586e814fb32949195f8f27bcc..39d0e7e1d6a40478ccff9a686700fa917c26fe21 100644 (file)
@@ -67,7 +67,7 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
             return nil
         }
 
-    case .Main:
+    case .Room_List:
         switch command_name {
         case ":add":
             if len(args) == 0 {
index 92d73d24155735318956222dc3bca908b94a12e7..b66bbae77fbe747d7b48f153f432fb9e2d41e5b9 100644 (file)
@@ -10,6 +10,7 @@ import "core:math/rand"
 import "core:mem"
 import "core:net"
 import "core:os"
+import "core:slice"
 import "core:strings"
 import "core:sync"
 import "core:thread"
@@ -46,8 +47,8 @@ App :: struct {
     info_bar: ^nc.Window,
     input_window: ^nc.Window,
 
-    room_list_window: ^nc.Window,
-    room_window: ^nc.Window,
+    room_list_window: Maybe(^nc.Window),
+    room_window: Maybe(^nc.Window),
 
     info_bar_content: string,
 
@@ -136,9 +137,12 @@ app_deinit :: proc(app: ^App) {
         delete(app.info_bar_content)
     }
 
-    if app.state == .Main {
-        nc.delwin(app.room_window)
-        nc.delwin(app.room_list_window)
+    if room_window, ok := app.room_window.?; ok {
+        nc.delwin(room_window)
+    }
+
+    if room_list_window, ok := app.room_list_window.?; ok {
+        nc.delwin(room_list_window)
     }
 
     nc.delwin(app.input_window)
@@ -154,14 +158,13 @@ app_deinit :: proc(app: ^App) {
 }
 
 app_update_room_list_window :: proc(app: ^App) {
-    if app.state != .Main {
+    room_list_window, ok := app.room_list_window.?
+
+    if !ok {
         return
     }
 
-    sync.mutex_lock(&app.mutex)
-    defer sync.mutex_unlock(&app.mutex)
-
-    nc.wclear(app.room_list_window)
+    nc.wclear(room_list_window)
 
     c_room_name_buffer: [ROOM_NAME_MAX_SIZE + 1]u8
 
@@ -184,18 +187,42 @@ app_update_room_list_window :: proc(app: ^App) {
 
         c_room_name := strings.unsafe_string_to_cstring(string(c_room_name_buffer[:]))
 
-        nc.wattron(app.room_list_window, room_color)
-        nc.mvwprintw(app.room_list_window, i32(i + 1), 1, c_room_name)
-        nc.wattroff(app.room_list_window, room_color)
+        nc.wattron(room_list_window, room_color)
+        nc.mvwprintw(room_list_window, i32(i + 1), 1, c_room_name)
+        nc.wattroff(room_list_window, room_color)
     }
 
     color := nc.COLOR_PAIR(3)
 
-    nc.wattron(app.room_list_window, color)
-    nc.box(app.room_list_window, 0, 0)
-    nc.wattroff(app.room_list_window, color)
+    if app.state == .Room_List {
+        color = nc.COLOR_PAIR(2)
+    }
+
+    nc.wattron(room_list_window, color)
+    nc.box(room_list_window, 0, 0)
+    nc.wattroff(room_list_window, color)
+
+    nc.wrefresh(room_list_window)
+}
+
+app_update_room_window :: proc(app: ^App) {
+    room_window, ok := app.room_window.?
+
+    if !ok {
+        return
+    }
+
+    color := nc.COLOR_PAIR(3)
+
+    if app.state == .Room {
+        color = nc.COLOR_PAIR(2)
+    }
+
+    nc.wattron(room_window, color)
+    nc.box(room_window, 0, 0)
+    nc.wattroff(room_window, color)
 
-    nc.wrefresh(app.room_list_window)
+    nc.wrefresh(room_window)
 }
 
 app_set_state :: proc(app: ^App, state: State) {
@@ -206,38 +233,35 @@ app_set_state :: proc(app: ^App, state: State) {
     app_update_info_bar(app)
 
     screen_height, screen_width := nc.getmaxyx(app.screen)
-
-    old_state := app.state
-
-    {
-        sync.mutex_lock(&app.mutex)
-        defer sync.mutex_unlock(&app.mutex)
-
-        app.state = state
-    }
-
     color := nc.COLOR_PAIR(3)
 
-    if old_state != .Main && state == .Main {
-        app.room_list_window = nc.newwin(screen_height - 2, 34, 0, 0)
-        app.room_window = nc.newwin(screen_height - 2, screen_width - 34, 0, 34)
-
-        app_update_room_list_window(app)
+    app.state = state
 
-        nc.wattron(app.room_window, color)
-        nc.box(app.room_window, 0, 0)
-        nc.wattroff(app.room_window, color)
+    if app.state == .Room_List || app.state == .Room {
+        if app.room_list_window == nil {
+            app.room_list_window = nc.newwin(screen_height - 2, 34, 0, 0)
+        }
 
-        nc.wrefresh(app.room_window)
-    } else if old_state == .Main && state != .Main {
-        nc.wclear(app.room_list_window)
-        nc.wclear(app.room_window)
+        if app.room_window == nil {
+            app.room_window = nc.newwin(screen_height - 2, screen_width - 34, 0, 34)
+        }
+    } else {
+        if room_list_window, ok := app.room_list_window.?; ok {
+            nc.wclear(room_list_window)
+            nc.wrefresh(room_list_window)
+            nc.delwin(room_list_window)
+        }
 
-        nc.wrefresh(app.room_list_window)
-        nc.wrefresh(app.room_window)
+        if room_window, ok := app.room_window.?; ok {
+            nc.wclear(room_window)
+            nc.wrefresh(room_window)
+            nc.delwin(room_window)
+        }
+    }
 
-        nc.delwin(app.room_list_window)
-        nc.delwin(app.room_window)
+    if app.state == .Room_List || app.state == .Room {
+        app_update_room_list_window(app)
+        app_update_room_window(app)
     }
 }
 
@@ -333,40 +357,37 @@ app_clear_box_message :: proc(app: ^App) {
     }
 }
 
-handle_getch :: proc(app: ^App, buffer_len, cursor_pos: ^int) -> (Maybe(int), bool) {
+handle_getch :: proc(app: ^App, buffer_len, cursor_pos: ^int) -> Maybe(int) {
     char := int(nc.wgetch(app.input_window))
 
     switch char {
-    case '\n':
-        return nil, false
-
     case nc.KEY_BACKSPACE:
         if cursor_pos^ != 0 {
             buffer_len^ -= 1
             cursor_pos^ -=1
         }
 
-        return nil, true
+        return nil
 
     case nc.KEY_LEFT:
         if cursor_pos^ != 0 {
             cursor_pos^ -= 1
         }
 
-        return nil, true
+        return nil
 
     case nc.KEY_RIGHT:
         if cursor_pos^ != buffer_len^ {
             cursor_pos^ += 1
         }
 
-        return nil, true
+        return nil
 
     case 0o400..=0o777:
-        return nil, true
+        return nil
 
     case:
-        return char, true
+        return char
     }
 }
 
@@ -389,37 +410,33 @@ app_get_input :: proc(
 
         nc.curs_set(1)
 
-        for {
-            maybe_char, keep_going := handle_getch(app, &buffer_len, &cursor_pos)
-
-            if !keep_going {
-                break
-            }
-
-            char, ok := maybe_char.?
+        input_loop: for {
+            char, ok := handle_getch(app, &buffer_len, &cursor_pos).?
 
-            if !ok {
-                continue
-            }
+            if ok {
+                switch char {
+                case '\n':
+                    break input_loop
 
-            if char == 27 {
-                buffer_len = 0
-                cursor_pos = 0
+                case 27:
+                    buffer_len = 0
+                    cursor_pos = 0
 
-                continue
-            }
+                    continue
+                }
 
-            buffer_len += 1
+                buffer_len += 1
 
-            mem.copy(
-                raw_data(buffer[cursor_pos + 1 : buffer_len]),
-                raw_data(buffer[cursor_pos : buffer_len - 1]),
-                int(buffer_len - cursor_pos - 1)
-            )
+                mem.copy(
+                    raw_data(buffer[cursor_pos + 1 : buffer_len]),
+                    raw_data(buffer[cursor_pos : buffer_len - 1]),
+                    int(buffer_len - cursor_pos - 1)
+                )
 
-            buffer[cursor_pos] = u8(char)
+                buffer[cursor_pos] = u8(char)
 
-            cursor_pos += 1
+                cursor_pos += 1
+            }
 
             buffer[buffer_len] = 0
             output := string(buffer[:buffer_len + 1])
@@ -457,12 +474,17 @@ Event :: enum {
     escape,
 }
 
-Command_Or_Event :: union {
+Input_Or_Event :: union {
     string,
     Event,
 }
 
-app_get_command_or_event :: proc(app: ^App, allocator := context.allocator) -> Command_Or_Event {
+app_get_input_or_event :: proc(
+    app: ^App,
+    allowed_events: []Event,
+    only_command := false,
+    allocator := context.allocator,
+) -> Input_Or_Event {
     context.allocator = allocator
 
     for {
@@ -476,47 +498,51 @@ app_get_command_or_event :: proc(app: ^App, allocator := context.allocator) -> C
 
         nc.curs_set(1)
 
-        for {
-            maybe_char, keep_going := handle_getch(app, &buffer_len, &cursor_pos)
-
-            if !keep_going {
-                break
-            }
-
-            char, ok := maybe_char.?
+        input_loop: for {
+            char, ok := handle_getch(app, &buffer_len, &cursor_pos).?
 
             if ok {
                 if buffer_len == 0 {
-                    switch char {
-                    case 'k': return Event.up
-                    case 'j': return Event.down
-                    case '\n': return Event.select
-                    case 27: return Event.escape
+                    switch {
+                    case char == 'k' && slice.contains(allowed_events, Event.up):
+                        return Event.up
+
+                    case char == 'j' && slice.contains(allowed_events, Event.down):
+                        return Event.down
+
+                    case char == '\n' && slice.contains(allowed_events, Event.select):
+                        return Event.select
+
+                    case char == 27 && slice.contains(allowed_events, Event.escape):
+                        return Event.escape
                     }
                 }
 
-                if char == 27 {
+                switch char {
+                case '\n':
+                    break input_loop
+
+                case 27:
                     buffer_len = 0
                     cursor_pos = 0
 
-                    continue
-                }
-
-                if (buffer_len == 0 && char != ':') && buffer[0] != ':' {
-                    continue
-                }
+                case:
+                    if only_command && (buffer_len == 0 && char != ':') && buffer[0] != ':' {
+                        continue
+                    }
 
-                buffer_len += 1
+                    buffer_len += 1
 
-                mem.copy(
-                    raw_data(buffer[cursor_pos + 1 : buffer_len]),
-                    raw_data(buffer[cursor_pos : buffer_len - 1]),
-                    int(buffer_len - cursor_pos - 1)
-                )
+                    mem.copy(
+                        raw_data(buffer[cursor_pos + 1 : buffer_len]),
+                        raw_data(buffer[cursor_pos : buffer_len - 1]),
+                        int(buffer_len - cursor_pos - 1)
+                    )
 
-                buffer[cursor_pos] = u8(char)
+                    buffer[cursor_pos] = u8(char)
 
-                cursor_pos += 1
+                    cursor_pos += 1
+                }
             }
 
             buffer[buffer_len] = 0
@@ -629,7 +655,8 @@ handle_state :: proc(app: ^App) {
         case .Connect_To_Host: state_connect_to_host(app)
         case .Invalid_Host: state_invalid_host(app)
 
-        case .Main: state_main(app)
+        case .Room_List: state_room_list(app)
+        case .Room: state_room(app)
         }
     }
 }
index 25a2ffb20797ff38bfe1ae7f8f89910c83dbc4f1..e16dd4b0e04ea041b7b8e95dd7d31fd39b2ef1bf 100644 (file)
@@ -32,7 +32,8 @@ State :: enum {
     Connect_To_Host,
     Invalid_Host,
 
-    Main,
+    Room_List,
+    Room,
 }
 
 state_load_config :: proc(app: ^App) {
@@ -430,7 +431,7 @@ state_connect_to_host :: proc(app: ^App) {
         app.host = host
     }
 
-    app_set_state(app, .Main)
+    app_set_state(app, .Room_List)
 }
 
 state_invalid_host :: proc(app: ^App) {
@@ -467,20 +468,19 @@ state_invalid_host :: proc(app: ^App) {
     app_set_state(app, .Connect_To_Host)
 }
 
-state_main :: proc(app: ^App) {
-    command_or_event := app_get_command_or_event(app)
-
-    defer {
-        #partial switch thing in command_or_event {
-        case string: delete(thing)
-        }
-    }
+state_room_list :: proc(app: ^App) {
+    input_or_event := app_get_input_or_event(
+        app,
+        { .up, .down, .select },
+        true,
+        context.temp_allocator,
+    )
 
-    switch thing in command_or_event{
+    switch thing in input_or_event {
     case string:
-        command := thing
+        input := thing
         
-        if err, ok := handle_command(app, command).?; ok {
+        if err, ok := handle_command(app, input).?; ok {
             if err != .Not_A_Command {
                 return
             }
@@ -491,7 +491,7 @@ state_main :: proc(app: ^App) {
     case Event:
         event := thing
 
-        switch event {
+        #partial switch event {
         case Event.up:
             if app.selected_room != 0 {
                 app.selected_room -= 1
@@ -505,7 +505,37 @@ state_main :: proc(app: ^App) {
             }
 
         case Event.select:
+            app_set_state(app, .Room)
+        }
+    }
+}
+
+state_room :: proc(app: ^App) {
+    input_or_event := app_get_input_or_event(
+        app,
+        { .escape },
+        false,
+        context.temp_allocator,
+    )
+
+    switch thing in input_or_event {
+    case string:
+        input := thing
+
+        if err, ok := handle_command(app, input).?; ok {
+            if err != .Not_A_Command {
+                return
+            }
+        } else {
+            return
+        }
+
+    case Event:
+        event := thing
+
+        #partial switch event {
         case Event.escape:
+            app_set_state(app, .Room_List)
         }
     }
 }
index ee7f0622c53f823c886b6f5d45c8e028a96420a3..ac1e78db54c3bf271c589833534b40bf50ef3f75 100755 (executable)
Binary files a/server/server and b/server/server differ