From da6cbce4ef35cd4f30e26d9ed126d86df367da99 Mon Sep 17 00:00:00 2001 From: maralorn Date: Thu, 28 Nov 2024 23:12:48 +0100 Subject: [PATCH] Try to prevent more flickering --- lib/NOM/IO.hs | 63 +++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/lib/NOM/IO.hs b/lib/NOM/IO.hs index c8271c3..82a159c 100644 --- a/lib/NOM/IO.hs +++ b/lib/NOM/IO.hs @@ -54,6 +54,13 @@ runUpdate output_builder_var state_var refresh_display_var updater input = do modifyTVar' output_builder_var (log_output :) modifyTVar' refresh_display_var (|| display_changed) +-- https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec +startAtomicUpdate :: Builder.Builder +startAtomicUpdate = "\x1b[?2026h" + +endAtomicUpdate :: Builder.Builder +endAtomicUpdate = "\x1b[?2026l" + writeStateToScreen :: forall state. Bool -> @@ -126,34 +133,36 @@ writeStateToScreen pad printed_lines_var nom_state_var nix_output_buffer_var ref output = toStrict . Builder.toLazyByteString - $ - -- when we clear the line, but don‘t use cursorUpLine, the cursor needs to be moved to the start for printing. - -- we do that before clearing because we can - memptyIfFalse (last_printed_line_count == 1) (Builder.stringUtf8 $ Terminal.setCursorColumnCode 0) - <> - -- Clear last output from screen. - -- First we clear the current line, if we have written on it. - memptyIfFalse (last_printed_line_count > 0) (Builder.stringUtf8 Terminal.clearLineCode) - <> - -- Then, if necessary we, move up and clear more lines. - stimesMonoid - (max (last_printed_line_count - 1) 0) - ( Builder.stringUtf8 (Terminal.cursorUpLineCode 1) -- Moves cursor one line up and to the beginning of the line. - <> Builder.stringUtf8 Terminal.clearLineCode -- We are avoiding to use clearFromCursorToScreenEnd - -- because it apparently triggers a flush on some terminals. - ) - <> - -- Insert the output to write to the screen. - ( output_to_print_with_newline_annotations & foldMap \(newline, line) -> - ( case newline of - StayInLine -> mempty - MoveToNextLine -> Builder.stringUtf8 (Terminal.cursorDownLineCode 1) - PrintNewLine -> Builder.byteString "\n" + $ startAtomicUpdate + <> + -- when we clear the line, but don‘t use cursorUpLine, the cursor needs to be moved to the start for printing. + -- we do that before clearing because we can + memptyIfFalse (last_printed_line_count == 1) (Builder.stringUtf8 $ Terminal.setCursorColumnCode 0) + <> + -- Clear last output from screen. + -- First we clear the current line, if we have written on it. + memptyIfFalse (last_printed_line_count > 0) (Builder.stringUtf8 Terminal.clearLineCode) + <> + -- Then, if necessary we, move up and clear more lines. + stimesMonoid + (max (last_printed_line_count - 1) 0) + ( Builder.stringUtf8 (Terminal.cursorUpLineCode 1) -- Moves cursor one line up and to the beginning of the line. + <> Builder.stringUtf8 Terminal.clearLineCode -- We are avoiding to use clearFromCursorToScreenEnd + -- because it apparently triggers a flush on some terminals. ) - <> Builder.byteString line - ) - -- Corner case: If nom is not outputting anything but we are printing output from nix, then we want to append a newline - <> memptyIfFalse (nom_output_length == 0 && nix_output_length > 0) Builder.byteString "\n" + <> + -- Insert the output to write to the screen. + ( output_to_print_with_newline_annotations & foldMap \(newline, line) -> + ( case newline of + StayInLine -> mempty + MoveToNextLine -> Builder.stringUtf8 (Terminal.cursorDownLineCode 1) + PrintNewLine -> Builder.byteString "\n" + ) + <> Builder.byteString line + ) + -- Corner case: If nom is not outputting anything but we are printing output from nix, then we want to append a newline + <> memptyIfFalse (nom_output_length == 0 && nix_output_length > 0) Builder.byteString "\n" + <> endAtomicUpdate -- Actually write to the buffer. We do this all in one step and with a strict -- ByteString so that everything is precalculated and the actual put is