Skip to content

Commit

Permalink
fix: unexpcted duplicate lines in kitty (sigoden#167)
Browse files Browse the repository at this point in the history
  • Loading branch information
sigoden authored and rooct committed Nov 30, 2023
1 parent c5b2187 commit dccaf0c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ fn start_directive(
let output = client.send_message(input)?;
if highlight {
let mut markdown_render = MarkdownRender::new(light_theme);
println!("{}", markdown_render.render(&output).trim());
println!("{}", markdown_render.render_block(&output).trim());
} else {
println!("{}", output.trim());
}
Expand Down
6 changes: 3 additions & 3 deletions src/render/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn cmd_render_stream(
let mut lines: Vec<&str> = text.split('\n').collect();
buffer = lines.pop().unwrap_or_default().to_string();
let output = lines.join("\n");
print_now!("{}\n", markdown_render.render(&output));
print_now!("{}\n", markdown_render.render_block(&output));
} else {
buffer = format!("{buffer}{text}");
if !(markdown_render.is_code_block()
Expand All @@ -36,14 +36,14 @@ pub fn cmd_render_stream(
|| buffer.starts_with('|'))
{
if let Some((output, remain)) = split_line(&buffer) {
print_now!("{}", markdown_render.render_line_stateless(&output));
print_now!("{}", markdown_render.render_line(&output));
buffer = remain;
}
}
}
}
ReplyStreamEvent::Done => {
let output = markdown_render.render(&buffer);
let output = markdown_render.render_block(&buffer);
print_now!("{}\n", output.trim_end());
break;
}
Expand Down
11 changes: 7 additions & 4 deletions src/render/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,17 @@ impl MarkdownRender {
}
}

pub fn render(&mut self, src: &str) -> String {
pub fn render_block(&mut self, src: &str) -> String {
src.split('\n')
.map(|line| self.render_line(line).unwrap_or_else(|| line.to_string()))
.map(|line| {
self.render_line_impl(line)
.unwrap_or_else(|| line.to_string())
})
.collect::<Vec<String>>()
.join("\n")
}

pub fn render_line_stateless(&self, line: &str) -> String {
pub fn render_line(&self, line: &str) -> String {
let output = if self.is_code_block() && detect_code_block(line).is_none() {
self.render_code_line(line)
} else {
Expand All @@ -76,7 +79,7 @@ impl MarkdownRender {
)
}

fn render_line(&mut self, line: &str) -> Option<String> {
fn render_line_impl(&mut self, line: &str) -> Option<String> {
if let Some(lang) = detect_code_block(line) {
match self.prev_line_type {
LineType::Normal | LineType::CodeEnd => {
Expand Down
61 changes: 27 additions & 34 deletions src/render/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,51 +39,62 @@ fn repl_render_stream_inner(
writer: &mut Stdout,
) -> Result<()> {
let mut last_tick = Instant::now();
let tick_rate = Duration::from_millis(100);
let tick_rate = Duration::from_millis(50);
let mut buffer = String::new();
let mut markdown_render = MarkdownRender::new(light_theme);
let terminal_columns = terminal::size()?.0;
let columns = terminal::size()?.0;
loop {
if abort.aborted() {
return Ok(());
}

if let Ok(evt) = rx.try_recv() {
recover_cursor(writer, terminal_columns, &buffer)?;

match evt {
ReplyStreamEvent::Text(text) => {
if !buffer.is_empty() {
let buffer_width = buffer.width() as u16;
let need_rows = (buffer_width + columns - 1) / columns;
let (col, row) = cursor::position()?;

if row + 1 >= need_rows {
if col == 0 {
queue!(writer, cursor::MoveTo(0, row - need_rows))?;
} else {
queue!(writer, cursor::MoveTo(0, row + 1 - need_rows))?;
}
} else {
queue!(
writer,
terminal::ScrollUp(need_rows - 1 - row),
cursor::MoveTo(0, 0)
)?;
}
}

if text.contains('\n') {
let text = format!("{buffer}{text}");
let mut lines: Vec<&str> = text.split('\n').collect();
buffer = lines.pop().unwrap_or_default().to_string();
let output = markdown_render.render(&lines.join("\n"));
let output = markdown_render.render_block(&lines.join("\n"));
for line in output.split('\n') {
queue!(
writer,
style::Print(line),
style::Print("\n"),
cursor::MoveLeft(terminal_columns),
cursor::MoveLeft(columns),
)?;
}
queue!(writer, style::Print(&buffer),)?;
} else {
buffer = format!("{buffer}{text}");
let output = markdown_render.render_line_stateless(&buffer);
let output = markdown_render.render_line(&buffer);
queue!(writer, style::Print(&output))?;
}

writer.flush()?;
}
ReplyStreamEvent::Done => {
let output = markdown_render.render_line_stateless(&buffer);
let trimed_output = output.trim_end();
if !trimed_output.is_empty() {
queue!(writer, style::Print(output.trim_end()))?;
writer.flush()?;
}

let (_, row) = cursor::position()?;
queue!(writer, cursor::MoveTo(0, row), style::Print("\n\n"))?;
queue!(writer, style::Print("\n"))?;
writer.flush()?;

break;
Expand Down Expand Up @@ -117,21 +128,3 @@ fn repl_render_stream_inner(
}
Ok(())
}

fn recover_cursor(writer: &mut Stdout, terminal_columns: u16, buffer: &str) -> Result<()> {
let buffer_rows = (u16::try_from(buffer.width()).unwrap_or(u16::MAX) + terminal_columns - 1)
/ terminal_columns;
let (_, row) = cursor::position()?;
if buffer_rows == 0 {
queue!(writer, cursor::MoveTo(0, row))?;
} else if row + 1 >= buffer_rows {
queue!(writer, cursor::MoveTo(0, row + 1 - buffer_rows))?;
} else {
queue!(
writer,
terminal::ScrollUp(buffer_rows - 1 - row),
cursor::MoveTo(0, 0)
)?;
}
Ok(())
}

0 comments on commit dccaf0c

Please sign in to comment.