mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-30 03:01:15 -03:00
Outputter to implement Write
By implementing Write directly, we can remove some local buffers and uses of Cursor. This both simplifies and optimizes the code.
This commit is contained in:
committed by
Peter Ammon
parent
64a40d2410
commit
dec5a64232
@@ -11,7 +11,7 @@
|
|||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::io::{Cursor, Write};
|
use std::io::{Result, Write};
|
||||||
use std::os::fd::RawFd;
|
use std::os::fd::RawFd;
|
||||||
use std::sync::atomic::{AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicU8, Ordering};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
@@ -79,24 +79,12 @@ fn index_for_color(c: RgbColor) -> u8 {
|
|||||||
c.to_term256_index()
|
c.to_term256_index()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a Cursor which have used write! on, return the slice of written bytes.
|
|
||||||
fn cursor_to_slice(cursor: Cursor<&mut [u8]>) -> &[u8] {
|
|
||||||
let len: usize = cursor
|
|
||||||
.position()
|
|
||||||
.try_into()
|
|
||||||
.expect("cursor position overflow");
|
|
||||||
let buff: &mut [u8] = cursor.into_inner();
|
|
||||||
&buff[..len]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_color_escape(outp: &mut Outputter, term: &Term, todo: &CStr, mut idx: u8, is_fg: bool) {
|
fn write_color_escape(outp: &mut Outputter, term: &Term, todo: &CStr, mut idx: u8, is_fg: bool) {
|
||||||
if term_supports_color_natively(term, idx.into()) {
|
if term_supports_color_natively(term, idx.into()) {
|
||||||
// Use tparm to emit color escape.
|
// Use tparm to emit color escape.
|
||||||
writembs!(outp, tparm1(todo, idx.into()));
|
writembs!(outp, tparm1(todo, idx.into()));
|
||||||
} else {
|
} else {
|
||||||
// We are attempting to bypass the term here. Generate the ANSI escape sequence ourself.
|
// We are attempting to bypass the term here. Generate the ANSI escape sequence ourself.
|
||||||
let mut buff = [0; 32];
|
|
||||||
let mut cursor = Cursor::new(&mut buff[..]);
|
|
||||||
if idx < 16 {
|
if idx < 16 {
|
||||||
// this allows the non-bright color to happen instead of no color working at all when a
|
// this allows the non-bright color to happen instead of no color working at all when a
|
||||||
// bright is attempted when only colors 0-7 are supported.
|
// bright is attempted when only colors 0-7 are supported.
|
||||||
@@ -108,15 +96,14 @@ fn write_color_escape(outp: &mut Outputter, term: &Term, todo: &CStr, mut idx: u
|
|||||||
idx -= 8;
|
idx -= 8;
|
||||||
}
|
}
|
||||||
write!(
|
write!(
|
||||||
cursor,
|
outp,
|
||||||
"\x1B[{}m",
|
"\x1B[{}m",
|
||||||
(if idx > 7 { 82 } else { 30 }) + i32::from(idx) + ((i32::from(!is_fg)) * 10)
|
(if idx > 7 { 82 } else { 30 }) + i32::from(idx) + ((i32::from(!is_fg)) * 10)
|
||||||
)
|
)
|
||||||
.expect("Writing to in-memory buffer should never fail");
|
.expect("Writing to in-memory buffer should never fail");
|
||||||
} else {
|
} else {
|
||||||
write!(cursor, "\x1B[{};5;{}m", if is_fg { 38 } else { 48 }, idx).unwrap();
|
write!(outp, "\x1B[{};5;{}m", if is_fg { 38 } else { 48 }, idx).unwrap();
|
||||||
}
|
}
|
||||||
outp.write_str(cursor_to_slice(cursor));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,18 +231,15 @@ pub fn write_color(&mut self, color: RgbColor, is_fg: bool) -> bool {
|
|||||||
// Foreground: ^[38;2;<r>;<g>;<b>m
|
// Foreground: ^[38;2;<r>;<g>;<b>m
|
||||||
// Background: ^[48;2;<r>;<g>;<b>m
|
// Background: ^[48;2;<r>;<g>;<b>m
|
||||||
let rgb = color.to_color24();
|
let rgb = color.to_color24();
|
||||||
let mut buff = [0; 128];
|
|
||||||
let mut cursor = Cursor::new(&mut buff[..]);
|
|
||||||
write!(
|
write!(
|
||||||
&mut cursor,
|
self,
|
||||||
"\x1B[{};2;{};{};{}m",
|
"\x1B[{};2;{};{};{}m",
|
||||||
if is_fg { 38 } else { 48 },
|
if is_fg { 38 } else { 48 },
|
||||||
rgb.r,
|
rgb.r,
|
||||||
rgb.g,
|
rgb.g,
|
||||||
rgb.b
|
rgb.b
|
||||||
)
|
)
|
||||||
.expect("should have written to buffer");
|
.expect("Outputter::write should never fail");
|
||||||
self.write_str(cursor_to_slice(cursor));
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,12 +425,6 @@ pub fn write_wstr(&mut self, str: &wstr) {
|
|||||||
self.maybe_flush();
|
self.maybe_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a narrow string.
|
|
||||||
pub fn write_str(&mut self, str: &[u8]) {
|
|
||||||
self.contents.extend_from_slice(str);
|
|
||||||
self.maybe_flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \return the "output" contents.
|
/// \return the "output" contents.
|
||||||
pub fn contents(&self) -> &[u8] {
|
pub fn contents(&self) -> &[u8] {
|
||||||
&self.contents
|
&self.contents
|
||||||
@@ -475,6 +453,21 @@ fn end_buffering(&mut self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Outputter implements Write, so it may be used as the receiver of the write! macro.
|
||||||
|
/// Only ASCII data should be written this way: do NOT assume that the receiver is UTF-8.
|
||||||
|
impl Write for Outputter {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||||
|
self.contents.extend_from_slice(buf);
|
||||||
|
self.maybe_flush();
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> Result<()> {
|
||||||
|
self.flush_to(self.fd);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// tputs accepts a function pointer that receives an int only.
|
// tputs accepts a function pointer that receives an int only.
|
||||||
// Use the following lock to redirect it to the proper outputter.
|
// Use the following lock to redirect it to the proper outputter.
|
||||||
// Note we can't use an owning Mutex because the tputs_writer must access it and Mutex is not
|
// Note we can't use an owning Mutex because the tputs_writer must access it and Mutex is not
|
||||||
|
|||||||
Reference in New Issue
Block a user