engine-q merge

This commit is contained in:
Fernando Herrera
2022-02-07 19:11:34 +00:00
1965 changed files with 119062 additions and 20 deletions

View File

@ -1,5 +0,0 @@
mod table;
mod wrap;
pub use table::{draw_table, StyledString, Table, TextStyle, Theme};
pub use wrap::Alignment;

View File

@ -1,3 +1,7 @@
<<<<<<< HEAD
=======
use nu_protocol::Config;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
use nu_table::{draw_table, StyledString, Table, TextStyle, Theme};
use std::collections::HashMap;
@ -25,6 +29,7 @@ fn main() {
let table = Table::new(headers, vec![rows; 3], Theme::rounded());
// FIXME: Config isn't available from here so just put these here to compile
let color_hm: HashMap<String, nu_ansi_term::Style> = HashMap::new();
<<<<<<< HEAD
// Capture the table as a string
let output_table = draw_table(&table, width, &color_hm);
@ -39,6 +44,14 @@ fn main() {
println!("{}", output_table)
}
}
=======
// get the default config
let config = Config::default();
// Capture the table as a string
let output_table = draw_table(&table, width, &color_hm, &config);
// Draw the table
println!("{}", output_table)
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
fn make_table_data() -> (Vec<&'static str>, Vec<&'static str>) {

View File

@ -1,5 +1,9 @@
use crate::wrap::{column_width, split_sublines, wrap, Alignment, Subline, WrappedCell};
use nu_ansi_term::{Color, Style};
<<<<<<< HEAD
=======
use nu_protocol::{Config, FooterMode};
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
use std::collections::HashMap;
use std::fmt::Write;
@ -240,6 +244,13 @@ impl TextStyle {
.bold(Some(true))
}
<<<<<<< HEAD
=======
pub fn default_field() -> TextStyle {
TextStyle::new().fg(Color::Green).bold(Some(true))
}
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub fn with_attributes(bo: bool, al: Alignment, co: Color) -> TextStyle {
TextStyle::new().alignment(al).fg(co).bold(Some(bo))
}
@ -607,15 +618,26 @@ impl Table {
}
#[derive(Debug)]
<<<<<<< HEAD
pub struct ProcessedTable<'a> {
pub headers: Vec<ProcessedCell<'a>>,
pub data: Vec<Vec<ProcessedCell<'a>>>,
=======
pub struct ProcessedTable {
pub headers: Vec<ProcessedCell>,
pub data: Vec<Vec<ProcessedCell>>,
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub theme: Theme,
}
#[derive(Debug)]
<<<<<<< HEAD
pub struct ProcessedCell<'a> {
pub contents: Vec<Vec<Subline<'a>>>,
=======
pub struct ProcessedCell {
pub contents: Vec<Vec<Subline>>,
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub style: TextStyle,
}
@ -625,6 +647,10 @@ pub struct WrappedTable {
pub headers: Vec<WrappedCell>,
pub data: Vec<Vec<WrappedCell>>,
pub theme: Theme,
<<<<<<< HEAD
=======
pub footer: Vec<WrappedCell>,
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
impl WrappedTable {
@ -636,7 +662,11 @@ impl WrappedTable {
let column_count = self.column_widths.len();
let mut output = String::new();
let sep_color = color_hm
<<<<<<< HEAD
.get("separator_color")
=======
.get("separator")
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
.unwrap_or(&Style::default())
.to_owned();
@ -685,6 +715,10 @@ impl WrappedTable {
);
}
}
<<<<<<< HEAD
=======
output.push('\n');
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
SeparatorPosition::Middle => {
for column in self.column_widths.iter().enumerate() {
@ -728,6 +762,10 @@ impl WrappedTable {
.push_str(&sep_color.paint(&self.theme.center.to_string()).to_string());
}
}
<<<<<<< HEAD
=======
output.push('\n');
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
SeparatorPosition::Bottom => {
for column in self.column_widths.iter().enumerate() {
@ -774,7 +812,10 @@ impl WrappedTable {
}
}
}
<<<<<<< HEAD
output.push('\n');
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
output
}
@ -784,7 +825,11 @@ impl WrappedTable {
color_hm: &HashMap<String, Style>,
) -> String {
let sep_color = color_hm
<<<<<<< HEAD
.get("separator_color")
=======
.get("separator")
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
.unwrap_or(&Style::default())
.to_owned();
@ -868,11 +913,16 @@ impl WrappedTable {
break;
}
<<<<<<< HEAD
writeln!(&mut total_output, "{}", output).unwrap();
=======
writeln!(&mut total_output, "{}", output).expect("writing should be done to buffer");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
total_output
}
<<<<<<< HEAD
fn print_table(&self, color_hm: &HashMap<String, Style>) -> String {
let mut output = String::new();
@ -880,15 +930,33 @@ impl WrappedTable {
{
let _ = nu_ansi_term::enable_ansi_support();
}
=======
fn print_table(&self, color_hm: &HashMap<String, Style>, config: &Config) -> String {
let mut output = String::new();
// TODO: This may be unnecessary after JTs changes. Let's remove it and see.
// #[cfg(windows)]
// {
// let _ = nu_ansi_term::enable_ansi_support();
// }
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
if self.data.is_empty() {
return output;
}
<<<<<<< HEAD
=======
// The top border
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
if self.theme.print_top_border {
output.push_str(&self.print_separator(SeparatorPosition::Top, color_hm));
}
<<<<<<< HEAD
=======
// The header
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
let skip_headers = (self.headers.len() == 2 && self.headers[1].max_width == 0)
|| (self.headers.len() == 1 && self.headers[0].max_width == 0);
@ -896,8 +964,13 @@ impl WrappedTable {
output.push_str(&self.print_cell_contents(&self.headers, color_hm));
}
<<<<<<< HEAD
let mut first_row = true;
=======
// The middle section
let mut first_row = true;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
for row in &self.data {
if !first_row {
if self.theme.separate_rows {
@ -914,20 +987,59 @@ impl WrappedTable {
output.push_str(&self.print_cell_contents(row, color_hm));
}
<<<<<<< HEAD
=======
match config.footer_mode {
FooterMode::Always => {
if self.theme.separate_header && !self.headers.is_empty() && !skip_headers {
output.push_str(&self.print_separator(SeparatorPosition::Middle, color_hm));
}
if !self.headers.is_empty() && !skip_headers {
output.push_str(&self.print_cell_contents(&self.footer, color_hm));
}
}
FooterMode::RowCount(r) => {
if self.data.len() as u64 > r {
if self.theme.separate_header && !self.headers.is_empty() && !skip_headers {
output.push_str(&self.print_separator(SeparatorPosition::Middle, color_hm));
}
if !self.headers.is_empty() && !skip_headers {
output.push_str(&self.print_cell_contents(&self.footer, color_hm));
}
}
}
_ => {} // Never and Auto aka auto get eaten and nothing happens
}
// The table finish
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
if self.theme.print_bottom_border {
output.push_str(&self.print_separator(SeparatorPosition::Bottom, color_hm));
}
<<<<<<< HEAD
if atty::is(atty::Stream::Stdout) {
// Draw the table with ansi colors
output
} else {
=======
// the atty is for when people do ls from vim, there should be no coloring there
if !config.use_ansi_coloring || !atty::is(atty::Stream::Stdout) {
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
// Draw the table without ansi colors
if let Ok(bytes) = strip_ansi_escapes::strip(&output) {
String::from_utf8_lossy(&bytes).to_string()
} else {
output
}
<<<<<<< HEAD
=======
} else {
// Draw the table with ansi colors
output
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
}
}
@ -1000,7 +1112,11 @@ pub fn maybe_truncate_columns(termwidth: usize, processed_table: &mut ProcessedT
processed_table.headers.push(ProcessedCell {
contents: vec![vec![Subline {
<<<<<<< HEAD
subline: "...",
=======
subline: "...".to_string(),
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
width: 3,
}]],
style: TextStyle::basic_center(),
@ -1009,7 +1125,11 @@ pub fn maybe_truncate_columns(termwidth: usize, processed_table: &mut ProcessedT
for entry in processed_table.data.iter_mut() {
entry.push(ProcessedCell {
contents: vec![vec![Subline {
<<<<<<< HEAD
subline: "...",
=======
subline: "...".to_string(),
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
width: 3,
}]],
style: TextStyle::basic_center(),
@ -1018,10 +1138,22 @@ pub fn maybe_truncate_columns(termwidth: usize, processed_table: &mut ProcessedT
}
}
<<<<<<< HEAD
pub fn draw_table(table: &Table, termwidth: usize, color_hm: &HashMap<String, Style>) -> String {
// Remove the edges, if used
let termwidth = if table.theme.print_left_border && table.theme.print_right_border {
termwidth - 2
=======
pub fn draw_table(
table: &Table,
termwidth: usize,
color_hm: &HashMap<String, Style>,
config: &Config,
) -> String {
// Remove the edges, if used
let termwidth = if table.theme.print_left_border && table.theme.print_right_border {
termwidth - 3
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
} else if table.theme.print_left_border || table.theme.print_right_border {
termwidth - 1
} else {
@ -1078,7 +1210,11 @@ pub fn draw_table(table: &Table, termwidth: usize, color_hm: &HashMap<String, St
&re_trailing,
);
<<<<<<< HEAD
wrapped_table.print_table(color_hm)
=======
wrapped_table.print_table(color_hm, config)
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
fn wrap_cells(
@ -1156,11 +1292,30 @@ fn wrap_cells(
output_data.push(output_row);
}
<<<<<<< HEAD
=======
let mut footer = vec![
WrappedCell {
lines: vec![],
max_width: 0,
style: TextStyle {
..Default::default()
},
};
output_headers.len()
];
footer.clone_from_slice(&output_headers[..]);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
WrappedTable {
column_widths,
headers: output_headers,
data: output_data,
theme: processed_table.theme,
<<<<<<< HEAD
=======
footer,
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
}

View File

@ -1,8 +1,16 @@
use crate::table::TextStyle;
<<<<<<< HEAD
use nu_ansi_term::Style;
use std::collections::HashMap;
use std::{fmt::Display, iter::Iterator};
use unicode_width::UnicodeWidthStr;
=======
use ansi_cut::AnsiCut;
use nu_ansi_term::Style;
use std::collections::HashMap;
use std::{fmt::Display, iter::Iterator};
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
#[derive(Debug, Clone, Copy)]
pub enum Alignment {
@ -12,24 +20,42 @@ pub enum Alignment {
}
#[derive(Debug)]
<<<<<<< HEAD
pub struct Subline<'a> {
pub subline: &'a str,
=======
pub struct Subline {
pub subline: String,
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub width: usize,
}
#[derive(Debug)]
<<<<<<< HEAD
pub struct Line<'a> {
pub sublines: Vec<Subline<'a>>,
pub width: usize,
}
#[derive(Debug)]
=======
pub struct Line {
pub sublines: Vec<Subline>,
pub width: usize,
}
#[derive(Debug, Clone)]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub struct WrappedLine {
pub line: String,
pub width: usize,
}
<<<<<<< HEAD
#[derive(Debug)]
=======
#[derive(Debug, Clone)]
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub struct WrappedCell {
pub lines: Vec<WrappedLine>,
pub max_width: usize,
@ -37,7 +63,11 @@ pub struct WrappedCell {
pub style: TextStyle,
}
<<<<<<< HEAD
impl<'a> Display for Line<'a> {
=======
impl Display for Line {
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut first = true;
for subline in &self.sublines {
@ -52,20 +82,76 @@ impl<'a> Display for Line<'a> {
}
}
<<<<<<< HEAD
=======
fn strip_ansi(astring: &str) -> String {
if let Ok(bytes) = strip_ansi_escapes::strip(astring) {
String::from_utf8_lossy(&bytes).to_string()
} else {
astring.to_string()
}
}
fn unicode_width_strip_ansi(astring: &str) -> usize {
let stripped_string: String = {
if let Ok(bytes) = strip_ansi_escapes::strip(astring) {
String::from_utf8_lossy(&bytes).to_string()
} else {
astring.to_string()
}
};
UnicodeWidthStr::width(&stripped_string[..])
}
// fn special_width(astring: &str) -> usize {
// // remove the zwj's '\u{200d}'
// // remove the fe0f's
// let stripped_string: String = {
// if let Ok(bytes) = strip_ansi_escapes::strip(astring) {
// String::from_utf8_lossy(&bytes).to_string()
// } else {
// astring.to_string()
// }
// };
// let no_zwj = stripped_string.replace('\u{200d}', "");
// let no_fe0f = no_zwj.replace('\u{fe0f}', "");
// UnicodeWidthStr::width(&no_fe0f[..])
// }
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub fn split_sublines(input: &str) -> Vec<Vec<Subline>> {
input
.split_terminator('\n')
.map(|line| {
line.split_terminator(' ')
.map(|x| Subline {
<<<<<<< HEAD
subline: x,
=======
subline: x.to_string(),
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
width: {
// We've tried UnicodeWidthStr::width(x), UnicodeSegmentation::graphemes(x, true).count()
// and x.chars().count() with all types of combinations. Currently, it appears that
// getting the max of char count and Unicode width seems to produce the best layout.
// However, it's not perfect.
<<<<<<< HEAD
let c = x.chars().count();
let u = UnicodeWidthStr::width(x);
=======
// let c = x.chars().count();
// let u = UnicodeWidthStr::width(x);
// std::cmp::min(c, u)
// let c = strip_ansi(x).chars().count();
// let u = special_width(x);
// std::cmp::max(c, u)
let c = strip_ansi(x).chars().count();
let u = unicode_width_strip_ansi(x);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
std::cmp::max(c, u)
},
})
@ -101,19 +187,31 @@ pub fn column_width(input: &[Vec<Subline>]) -> usize {
}
fn split_word(cell_width: usize, word: &str) -> Vec<Subline> {
<<<<<<< HEAD
use unicode_width::UnicodeWidthChar;
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
let mut output = vec![];
let mut current_width = 0;
let mut start_index = 0;
let mut end_index;
<<<<<<< HEAD
for c in word.char_indices() {
=======
let word_no_ansi = strip_ansi(word);
for c in word_no_ansi.char_indices() {
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
if let Some(width) = c.1.width() {
end_index = c.0;
if current_width + width > cell_width {
output.push(Subline {
<<<<<<< HEAD
subline: &word[start_index..end_index],
=======
subline: word.cut(start_index..end_index),
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
width: current_width,
});
@ -125,9 +223,15 @@ fn split_word(cell_width: usize, word: &str) -> Vec<Subline> {
}
}
<<<<<<< HEAD
if start_index != word.len() {
output.push(Subline {
subline: &word[start_index..],
=======
if start_index != word_no_ansi.len() {
output.push(Subline {
subline: word.cut(start_index..),
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
width: current_width,
});
}
@ -135,9 +239,15 @@ fn split_word(cell_width: usize, word: &str) -> Vec<Subline> {
output
}
<<<<<<< HEAD
pub fn wrap<'a>(
cell_width: usize,
mut input: impl Iterator<Item = Subline<'a>>,
=======
pub fn wrap(
cell_width: usize,
mut input: impl Iterator<Item = Subline>,
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
color_hm: &HashMap<String, Style>,
re_leading: &regex::Regex,
re_trailing: &regex::Regex,
@ -165,7 +275,11 @@ pub fn wrap<'a>(
// If this is a really long single word, we need to split the word
if current_line.len() == 1 && current_width > cell_width {
max_width = cell_width;
<<<<<<< HEAD
let sublines = split_word(cell_width, current_line[0].subline);
=======
let sublines = split_word(cell_width, &current_line[0].subline);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
for subline in sublines {
let width = subline.width;
lines.push(Line {
@ -200,7 +314,11 @@ pub fn wrap<'a>(
None => {
if current_width > cell_width {
// We need to break up the last word
<<<<<<< HEAD
let sublines = split_word(cell_width, current_line[0].subline);
=======
let sublines = split_word(cell_width, &current_line[0].subline);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
for subline in sublines {
let width = subline.width;
lines.push(Line {
@ -235,7 +353,11 @@ pub fn wrap<'a>(
first = false;
current_line_width = subline.width;
}
<<<<<<< HEAD
current_line.push_str(subline.subline);
=======
current_line.push_str(&subline.subline);
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
}
if current_line_width > current_max {