diff --git a/colors.v b/colors.v index 970006e0..f4bd249d 100644 --- a/colors.v +++ b/colors.v @@ -2,13 +2,30 @@ module palette import tauraamui.bobatea as tea +// TODO(tauraamui): consolidate all used colors into a core palette/swatch set +// and alias reference off of that only in the places/models they are used with +// alternative names, instead of here. This file is getting messy and out of hand. pub const theme_bg_color = matte_black_bg_color pub const matte_black_bg_color = tea.Color{ 20, 20, 20 } +pub const petal_pink_color = tea.Color{ 245, 191, 243 } +pub const petal_green_color = tea.Color{ 97, 242, 136 } +pub const petal_red_color = tea.Color{ 245, 42, 42 } + +pub const status_green = tea.Color{ 145, 237, 145 } +pub const status_orange = tea.Color{ 237, 207, 123 } +pub const status_lilac = tea.Color{ 194, 110, 230 } +pub const status_dark_lilac = tea.Color{ 154, 119, 209 } +pub const status_cyan = tea.Color{ 138, 222, 237 } +pub const status_purple = tea.Color{ 130, 144, 250 } + +pub const error_color = petal_red_color + + pub const matte_black_fg_color = tea.Color.ansi(232) pub const matte_white_fg_color = tea.Color{ 230, 230, 230 } pub const bright_off_white_fg_color = tea.Color{ 255, 255, 255 } -pub const bright_red_fg_color = tea.Color{ 245, 42, 42 } +// pub const bright_red_fg_color = tea.Color{ 245, 42, 42 } pub const subtle_text_fg_color = tea.Color.ansi(249) pub const help_fg_color = tea.Color.ansi(241) @@ -17,30 +34,12 @@ pub const selected_highlight_bg_color = tea.Color.ansi(239) pub const subtle_border_fg_color = petal_pink_color -pub const petal_pink_color = tea.Color{ - r: 245 - g: 191 - b: 243 -} - -pub const petal_green_color = tea.Color{ - r: 97 - g: 242 - b: 136 -} pub const status_bar_bg_color = tea.Color.ansi(234) pub const status_file_name_bg_color = tea.Color{ 86, 86, 86 } pub const status_branch_name_bg_color = tea.Color{ 154, 119, 209 } pub const status_cursor_pos_bg_color = tea.Color{ 245, 42, 42 } -pub const status_green = tea.Color{ 145, 237, 145 } -pub const status_orange = tea.Color{ 237, 207, 123 } -pub const status_lilac = tea.Color{ 194, 110, 230 } -pub const status_dark_lilac = tea.Color{ 154, 119, 209 } -pub const status_cyan = tea.Color{ 138, 222, 237 } -pub const status_purple = tea.Color{ 130, 144, 250 } - pub fn fg_color(background_color tea.Color) tea.Color { s_r := f32(background_color.r) / 255 s_g := f32(background_color.g) / 255 diff --git a/editor.v b/editor.v index 608c2ac5..6c398492 100644 --- a/editor.v +++ b/editor.v @@ -44,8 +44,9 @@ struct EditorModel { id int file_path string mut: - focused bool - cursor_pos ModelCursorPos + focused bool + show_border bool = true + cursor_pos ModelCursorPos width int height int @@ -167,6 +168,15 @@ fn (mut m EditorModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { else {} } } + ToggleEditorShowBorderMsg { + if msg.id == m.id { + m.show_border = msg.show + } else { + if msg.show == false { + m.show_border = true + } + } + } EditorCursorUpMsg { if m.focused { m.cursor_pos = m.cursor_pos.up() @@ -182,10 +192,24 @@ fn (mut m EditorModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { return m.clone(), tea.batch_array(cmds) } +const active_editor_border_color = palette.petal_pink_color +const inactive_editor_border_color = palette.status_dark_lilac + fn (m EditorModel) view(mut ctx tea.Context) { ctx.set_clip_area(tea.ClipArea{ 0, 0, m.width, m.height }) defer { ctx.clear_clip_area() } + if m.show_border { + border_color := if m.focused { active_editor_border_color } else { inactive_editor_border_color } + ctx.set_color(border_color) + for y in 0..m.height { + ctx.draw_text(0, y, '│') + } + ctx.reset_color() + } + + ctx.push_offset(tea.Offset{ x: 1 }) + for y, l in m.lines { ctx.draw_text(0, y, l.replace('\t', ' ')) } diff --git a/editor_workspace.v b/editor_workspace.v index eac61127..a0b28f30 100644 --- a/editor_workspace.v +++ b/editor_workspace.v @@ -101,6 +101,19 @@ fn unfocus_editor(editor_id int) tea.Cmd { } } +struct ToggleEditorShowBorderMsg { + id int + show bool +} + +fn toggle_editor_show_border(editor_id int, show bool) tea.Cmd { + return fn [editor_id, show] () tea.Msg { + return ToggleEditorShowBorderMsg{ + id: editor_id + show: show + } + } +} fn raise_error(error string) tea.Cmd { return tea.sequence(display_error(error), error_log(error), hide_error_after(6 * time.second)) @@ -173,6 +186,7 @@ fn get_branch(execute fn (cmd string) os.Result) string { return res.output } +// NOTE(tauraamui) [08/01/26]: do these actually need to be public, not sure, doubt it check when have time pub struct VerticalSplitMsg {} pub fn split_vertically() tea.Msg { @@ -185,6 +199,20 @@ pub fn close_active_split() tea.Msg { return CloseActiveSplitMsg{} } +enum SplitMoveDir { + left + right +} + +struct SwitchActiveSplitMsg { + dir SplitMoveDir +} + +fn switch_active_split(dir SplitMoveDir) tea.Cmd { + return fn [dir] () tea.Msg { + return SwitchActiveSplitMsg{dir} + } +} fn (mut m EditorWorkspaceModel) update_dialog(msg tea.Msg) (?tea.Model, ?tea.Cmd) { if msg is CloseDialogMsg { @@ -260,53 +288,10 @@ fn (mut m EditorWorkspaceModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { .runes { match msg.string() { 'h' { - // move to previous split (left) - if m.split_tree.count() > 1 { - old_id := m.split_tree.active_editor_id - moved := m.split_tree.navigate_prev(m.tmux_wrapped) - - if moved == false { - os.execute('tmux select-pane -L') - } else { - new_id := m.split_tree.active_editor_id - m.active_editor_id = new_id - - cmds << tea.sequence( - unfocus_editor(old_id), - focus_editor(new_id), - query_editor_data(new_id), - query_pwd_git_branch - ) - } - } else { - if m.tmux_wrapped { - os.execute('tmux select-pane -L') - } - } + cmds << switch_active_split(.left) } 'l' { - // move to next split (right) - if m.split_tree.count() > 1 { - old_id := m.split_tree.active_editor_id - moved := m.split_tree.navigate_next(m.tmux_wrapped) - if moved == false { - os.execute('tmux select-pane -R') - } else { - new_id := m.split_tree.active_editor_id - m.active_editor_id = new_id - - cmds << tea.sequence( - unfocus_editor(old_id), - focus_editor(new_id), - query_editor_data(new_id), - query_pwd_git_branch - ) - } - } else { - if m.tmux_wrapped { - os.execute('tmux select-pane -R') - } - } + cmds << switch_active_split(.right) } else {} } @@ -325,53 +310,10 @@ fn (mut m EditorWorkspaceModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { cmds << switch_mode(.navigation) } "ctrl+w+h" { - // move to previous split (left) - if m.split_tree.count() > 1 { - old_id := m.split_tree.active_editor_id - moved := m.split_tree.navigate_prev(m.tmux_wrapped) - - if moved == false { - os.execute('tmux select-pane -L') - } else { - new_id := m.split_tree.active_editor_id - m.active_editor_id = new_id - - cmds << tea.sequence( - unfocus_editor(old_id), - focus_editor(new_id), - query_editor_data(new_id), - query_pwd_git_branch - ) - } - } else { - if m.tmux_wrapped { - os.execute('tmux select-pane -L') - } - } + cmds << switch_active_split(.left) } "ctrl+w+l" { - // move to next split (right) - if m.split_tree.count() > 1 { - old_id := m.split_tree.active_editor_id - moved := m.split_tree.navigate_next(m.tmux_wrapped) - if moved == false { - os.execute('tmux select-pane -R') - } else { - new_id := m.split_tree.active_editor_id - m.active_editor_id = new_id - - cmds << tea.sequence( - unfocus_editor(old_id), - focus_editor(new_id), - query_editor_data(new_id), - query_pwd_git_branch - ) - } - } else { - if m.tmux_wrapped { - os.execute('tmux select-pane -R') - } - } + cmds << switch_active_split(.right) } else {} } @@ -456,7 +398,12 @@ fn (mut m EditorWorkspaceModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { cmds << u_cmd } - cmds << tea.sequence(focus_editor(editor_id), query_editor_data(editor_id), query_pwd_git_branch) + cmds << tea.sequence( + focus_editor(editor_id), + toggle_editor_show_border(editor_id, false), + query_editor_data(editor_id), + query_pwd_git_branch + ) cmds << debug_log("opened file ${msg.file_path} into model of id ${editor_id}") } VerticalSplitMsg { @@ -475,9 +422,11 @@ fn (mut m EditorWorkspaceModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { m.active_editor_id = m.split_tree.active_editor_id cmds << tea.sequence( - unfocus_editor(old_id), // Unfocus the old editor + unfocus_editor(old_id), + toggle_editor_show_border(m.split_tree.get_leftmost_id(), false), focus_editor(new_id), query_editor_data(new_id), + query_pwd_git_branch, tea.emit_resize ) } @@ -494,12 +443,67 @@ fn (mut m EditorWorkspaceModel) update(msg tea.Msg) (tea.Model, ?tea.Cmd) { // focus the new active editor cmds << tea.sequence( focus_editor(m.active_editor_id), + toggle_editor_show_border(m.split_tree.get_leftmost_id(), false), query_editor_data(m.active_editor_id), - query_pwd_git_branch + query_pwd_git_branch, + tea.emit_resize ) } } } + SwitchActiveSplitMsg { + match msg.dir { + .left { + // move to previous split (left) + if m.split_tree.count() > 1 { + old_id := m.split_tree.active_editor_id + moved := m.split_tree.navigate_prev(m.tmux_wrapped) + + if moved == false { + os.execute('tmux select-pane -L') + } else { + new_id := m.split_tree.active_editor_id + m.active_editor_id = new_id + + cmds << tea.sequence( + unfocus_editor(old_id), + focus_editor(new_id), + query_editor_data(new_id), + query_pwd_git_branch + ) + } + } else { + if m.tmux_wrapped { + os.execute('tmux select-pane -L') + } + } + } + .right { + // move to next split (right) + if m.split_tree.count() > 1 { + old_id := m.split_tree.active_editor_id + moved := m.split_tree.navigate_next(m.tmux_wrapped) + if moved == false { + os.execute('tmux select-pane -R') + } else { + new_id := m.split_tree.active_editor_id + m.active_editor_id = new_id + + cmds << tea.sequence( + unfocus_editor(old_id), + focus_editor(new_id), + query_editor_data(new_id), + query_pwd_git_branch + ) + } + } else { + if m.tmux_wrapped { + os.execute('tmux select-pane -R') + } + } + } + } + } EditorDataResultMsg { m.active_editor_data = msg.data } @@ -712,7 +716,7 @@ fn (m EditorWorkspaceModel) render_status_blocks(mut ctx tea.Context) { fn (m EditorWorkspaceModel) render_leader_or_command_user_input_text(mut ctx tea.Context) { if err_msg := m.error_msg { - ctx.set_color(palette.bright_red_fg_color) + ctx.set_color(palette.error_color) ctx.draw_text(1, ctx.window_height() - 1, err_msg) ctx.reset_color() return diff --git a/split_tree.v b/split_tree.v index 4eaff165..13fe7c08 100644 --- a/split_tree.v +++ b/split_tree.v @@ -279,6 +279,25 @@ pub: height int } +pub fn (t SplitTree) get_leftmost_id() int { + if root := t.root { + return t.find_leftmost_id(root) + } + return -1 +} + +fn (t SplitTree) find_leftmost_id(node SplitNode) int { + match node { + EditorLeaf { + return node.editor_id + } + SplitContainer { + // the leftmost editor is always in the first child + return t.find_leftmost_id(node.children[0]) + } + } +} + pub fn (t SplitTree) get_layout(total_width int, total_height int) []LayoutRect { mut rects := []LayoutRect{} if root := t.root {