diff --git a/src/etui/backend/erlang.gleam b/src/etui/backend/erlang.gleam index 640baf2..45e5d21 100644 --- a/src/etui/backend/erlang.gleam +++ b/src/etui/backend/erlang.gleam @@ -109,8 +109,8 @@ fn init_terminal(mouse: Bool) -> Result(ErlangTerminalState, Error) { enter_raw_ffi() set_raw_state(True) let #(cols, rows) = case window_size_ffi() { - Ok(#(c, r)) -> #(c, r) - Error(_) -> #(80, 24) + Ok(#(c, r)) -> #(c - 1, r) + Error(_) -> #(79, 24) } install_sigint_cleanup_ffi(fn() { terminal_cleanup() }) Ok(ErlangTerminalState( @@ -144,12 +144,12 @@ fn poll_input( } case window_size_ffi() { Ok(#(c, r)) -> - case c == state.cols && r == state.rows { + case c - 1 == state.cols && r == state.rows { True -> Ok(#(input_event, state)) False -> Ok(#( - backend.Resize(c, r), - ErlangTerminalState(..state, cols: c, rows: r), + backend.Resize(c - 1, r), + ErlangTerminalState(..state, cols: c - 1, rows: r), )) } Error(_) -> Ok(#(input_event, state)) @@ -160,8 +160,8 @@ fn get_terminal_size( state: ErlangTerminalState, ) -> Result(#(TerminalSize, ErlangTerminalState), Error) { case window_size_ffi() { - Ok(#(w, h)) -> Ok(#(backend.TerminalSize(width: w, height: h), state)) - Error(_) -> Ok(#(backend.TerminalSize(width: 80, height: 24), state)) + Ok(#(w, h)) -> Ok(#(backend.TerminalSize(width: w - 1, height: h), state)) + Error(_) -> Ok(#(backend.TerminalSize(width: 79, height: 24), state)) } } diff --git a/src/etui/widgets/input.gleam b/src/etui/widgets/input.gleam index dbaa646..7449ba5 100644 --- a/src/etui/widgets/input.gleam +++ b/src/etui/widgets/input.gleam @@ -13,6 +13,7 @@ import etui/buffer import etui/geometry import etui/style import etui/text +import gleam/int import gleam/string // ───────────────────────────────────────────────────────────────── @@ -228,8 +229,16 @@ pub fn render( True -> widget.prompt <> value_display False -> widget.prompt <> widget.placeholder } - let truncated = text.truncate(display_text, area.size.width - 1, "") - let padded = text.pad_right(truncated, area.size.width) + let c = text.cell_width(widget.prompt) + state.cursor + let w_avail = int.max(1, area.size.width) + let view_start = case c >= w_avail { + True -> c - w_avail + 1 + False -> 0 + } + let prefix = text.truncate(display_text, view_start, "") + let suffix = string.drop_start(display_text, string.length(prefix)) + let truncated = text.truncate(suffix, w_avail, "") + let padded = text.pad_right(truncated, w_avail) let modifier = case has_value { True -> style.bold() False -> style.none()