# Overwriting previous terminal output with built-in functions

**URL:** https://discourse.julialang.org/t/overwriting-previous-terminal-output-with-built-in-functions/99593
**Category:** General Usage
**Tags:** repl
**Created:** [May 30, 2023, 9:03am UTC](https://discourse.julialang.org/t/overwriting-previous-terminal-output-with-built-in-functions/99593 "2023-05-30T09:03:33Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![TheLateKronos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thelatekronos/32/12824_2.png) [@TheLateKronos](https://discourse.julialang.org/u/TheLateKronos)
#### Post date: [May 30, 2023, 9:03am UTC](https://discourse.julialang.org/t/overwriting-previous-terminal-output-with-built-in-functions/99593/1 "2023-05-30T09:03:33Z")

</div>

This is heavily related to [How clear the printed content in terminal and print to the same line?](https://discourse.julialang.org/t/how-clear-the-printed-content-in-terminal-and-print-to-the-same-line/19549), which provides some good answers.

The linked thread has examples that I used to create the showcase function below:

```julia
julia> function test()
               print("ayy")
               print("\e[2K") # clear whole line
               print("\e[1G") # move cursor to column 1
               print("new line")
       end
test (generic function with 1 method)

julia> test()
new line

```

So it seems like these escape sequences can do what is needed. However, I just stumbled upon a bunch of functions inside `REPL.LineEdit`, with promising names. I was hoping they would be easier to reason about than obscure codes. Below is the output from tab-completing the functions in the module that start with `edit_`:

```julia
julia> import REPL

julia> REPL.LineEdit.edit_

edit_abort edit_backspace
edit_clear edit_copy_region
edit_delete edit_delete_next_word
edit_delete_prev_word edit_exchange_point_and_mark
edit_indent edit_indent_left
edit_indent_right edit_input
edit_insert edit_insert_last_word
edit_insert_newline edit_insert_tab
edit_kill_line edit_kill_line_backwards
edit_kill_line_forwards edit_kill_region
edit_lower_case edit_move_down
edit_move_left edit_move_right
edit_move_up edit_move_word_left
edit_move_word_right edit_redo!
edit_replace_word_right edit_shift_move
edit_splice! edit_tab
edit_title_case edit_transpose_chars
edit_transpose_lines_down! edit_transpose_lines_up!
edit_transpose_words edit_undo!
edit_upper_case edit_werase
edit_yank edit_yank_pop

```

Are these functions something that users could/should use? Are there other, better ways to overwrite previous terminal outputs? Or is the status just “get good and learn ANSI escape codes”?

---

<div class="post-metadata">

### Author: ![TheLateKronos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thelatekronos/32/12824_2.png) [@TheLateKronos](https://discourse.julialang.org/u/TheLateKronos)
#### Post date: [May 30, 2023, 9:46am UTC](https://discourse.julialang.org/t/overwriting-previous-terminal-output-with-built-in-functions/99593/2 "2023-05-30T09:46:15Z")

</div>

It looks like `REPL.Terminals` has what I am looking for in the functions starting with `cmove`:

```julia
julia> REPL.Terminals.cmove

cmove cmove_col cmove_down
cmove_left cmove_line_down cmove_line_up
cmove_right cmove_up

```

It just requires a terminal as the first argument, which you can get a handle to via the following line (From [this](https://discourse.julialang.org/t/how-to-get-a-handle-to-the-terminal/99592) discourse discussion on the topic):

```julia
import REPL
terminal = REPL.Terminals.TTYTerminal(string(), stdin, stdout, stderr)

```

By inspecting the source, it turns out the these functions are exactly just pretty packaging of the escape sequences. Here are lines 113 to 121 from the file defining `REPL.Terminals.clear_line`

```julia
const CSI = "\x1b["

cmove_up(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)A")
cmove_down(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)B")
cmove_right(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)C")
cmove_left(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)D")
cmove_line_up(t::UnixTerminal, n) = (cmove_up(t, n); cmove_col(t, 1))
cmove_line_down(t::UnixTerminal, n) = (cmove_down(t, n); cmove_col(t, 1))
cmove_col(t::UnixTerminal, n) = (write(t.out_stream, '\r'); n > 1 && cmove_right(t, n-1))

```

With this, I was able to put together this example, completely without learning the codes. Sweet!

```julia
import REPL
terminal = REPL.Terminals.TTYTerminal(string(), stdin, stdout, stderr)
println() # Dummy line
for i in (1, "two", :III, "||||")
	REPL.Terminals.cmove_left(terminal, length(string(i)))
	REPL.Terminals.cmove_line_up(terminal)
	println(i)
	sleep(0.5)
end
println("Watch the final number dissapear above me")
sleep(0.5)
REPL.Terminals.cmove_line_up(terminal, 2)
REPL.Terminals.clear_line(terminal)
REPL.Terminals.cmove_line_down(terminal, 3) # If not, next input is above previous output, which looks funny

```

[https://global.discourse-cdn.com/julialang/original/3X/e/3/e3462d91b15938cae094755d4ce7b3a92c6f6e7f.mp4](https://global.discourse-cdn.com/julialang/original/3X/e/3/e3462d91b15938cae094755d4ce7b3a92c6f6e7f.mp4)

---

<div class="post-metadata">

### Author: ![caleb-allen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/caleb-allen/32/14054_2.png) [@caleb-allen](https://discourse.julialang.org/u/caleb-allen)
#### Post date: [May 30, 2023, 12:46pm UTC](https://discourse.julialang.org/t/overwriting-previous-terminal-output-with-built-in-functions/99593/3 "2023-05-30T12:46:20Z")

</div>

This is very interesting! Do you think this could overwrite input as well?

I’m working on VimBindings.jl and am looking for ways to implement [Replace mode](https://github.com/caleb-allen/VimBindings.jl/issues/32), I’m interested in using some terminal hacking for that.

---

<div class="post-metadata">

### Author: ![TheLateKronos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thelatekronos/32/12824_2.png) [@TheLateKronos](https://discourse.julialang.org/u/TheLateKronos)
#### Post date: [May 30, 2023, 1:20pm UTC](https://discourse.julialang.org/t/overwriting-previous-terminal-output-with-built-in-functions/99593/4 "2023-05-30T13:20:22Z")

</div>

It seemed like one could move the cursor arbitrarily, so anything in the terminal should be fair game. That would naturally include previous input.

If you want changed to the current input, then I suspect the functions inside `LineEdit` from the original post are what you want. They do however not take a terminal as argument, and I was unable to understand how to use them based on their methods.
