Allow configuration of multiline prompt color (#531)

* make multiline prompt color configurable

* remove unnused use statements

* minor comment update

* Clippy fix

new lints from rust 1.67

* Cargo fmt

---------

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
This commit is contained in:
Doug Kelkhoff 2023-01-27 09:58:25 -05:00 committed by GitHub
parent 3d83306b2d
commit e1366260c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 60 additions and 60 deletions

View File

@ -15,7 +15,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -47,7 +47,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -26,7 +26,7 @@ impl Prompt for CustomPrompt {
{ {
let old = self.0.get(); let old = self.0.get();
self.0.set(old + 1); self.0.set(old + 1);
Cow::Owned(format!("[{}]", old)) Cow::Owned(format!("[{old}]"))
} }
} }
@ -64,7 +64,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -149,7 +149,7 @@ fn main() -> Result<()> {
line_editor.print_history()?; line_editor.print_history()?;
continue; continue;
} }
println!("Our buffer: {}", buffer); println!("Our buffer: {buffer}");
#[cfg(any(feature = "sqlite", feature = "sqlite-dynlib"))] #[cfg(any(feature = "sqlite", feature = "sqlite-dynlib"))]
if !buffer.is_empty() { if !buffer.is_empty() {
line_editor line_editor
@ -165,7 +165,7 @@ fn main() -> Result<()> {
// Prompt has been cleared and should start on the next line // Prompt has been cleared and should start on the next line
} }
Err(err) => { Err(err) => {
println!("Error: {:?}", err); println!("Error: {err:?}");
} }
} }
} }

View File

@ -51,13 +51,12 @@ fn print_events_helper() -> Result<()> {
} }
_ => { _ => {
println!( println!(
"Keycode: {:?}; Modifier {:?}; Flags {:#08b}\r", "Keycode: {code:?}; Modifier {modifiers:?}; Flags {modifiers:#08b}\r"
code, modifiers, modifiers
); );
} }
} }
} else { } else {
println!("Event::{:?}\r", event); println!("Event::{event:?}\r");
} }
// hit the esc key to git out // hit the esc key to git out

View File

@ -24,7 +24,7 @@ fn main() {
let mut i = 1; let mut i = 1;
loop { loop {
sleep(Duration::from_secs(1)); sleep(Duration::from_secs(1));
assert!(p_clone.print(format!("Message {} delivered.", i)).is_ok()); assert!(p_clone.print(format!("Message {i} delivered.")).is_ok());
i += 1; i += 1;
} }
}); });
@ -34,7 +34,7 @@ fn main() {
sleep(Duration::from_secs(3)); sleep(Duration::from_secs(3));
for _ in 0..10 { for _ in 0..10 {
sleep(Duration::from_millis(1)); sleep(Duration::from_millis(1));
assert!(p_sender.send(format!("Fast Hello !")).is_ok()); assert!(p_sender.send("Fast Hello !".to_string()).is_ok());
} }
}); });
@ -45,7 +45,7 @@ fn main() {
if let Ok(sig) = line_editor.read_line(&prompt) { if let Ok(sig) = line_editor.read_line(&prompt) {
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -20,7 +20,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -20,7 +20,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -22,7 +22,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -17,34 +17,31 @@ fn main() -> Result<()> {
fn get_all_keybinding_info() { fn get_all_keybinding_info() {
println!("--Key Modifiers--"); println!("--Key Modifiers--");
for mods in get_reedline_keybinding_modifiers().iter() { for mods in get_reedline_keybinding_modifiers().iter() {
println!("{}", mods); println!("{mods}");
} }
println!("\n--Modes--"); println!("\n--Modes--");
for modes in get_reedline_prompt_edit_modes().iter() { for modes in get_reedline_prompt_edit_modes().iter() {
println!("{}", modes); println!("{modes}");
} }
println!("\n--Key Codes--"); println!("\n--Key Codes--");
for kcs in get_reedline_keycodes().iter() { for kcs in get_reedline_keycodes().iter() {
println!("{}", kcs); println!("{kcs}");
} }
println!("\n--Reedline Events--"); println!("\n--Reedline Events--");
for rle in get_reedline_reedline_events().iter() { for rle in get_reedline_reedline_events().iter() {
println!("{}", rle); println!("{rle}");
} }
println!("\n--Edit Commands--"); println!("\n--Edit Commands--");
for edit in get_reedline_edit_commands().iter() { for edit in get_reedline_edit_commands().iter() {
println!("{}", edit); println!("{edit}");
} }
println!("\n--Default Keybindings--"); println!("\n--Default Keybindings--");
for (mode, modifier, code, event) in get_reedline_default_keybindings() { for (mode, modifier, code, event) in get_reedline_default_keybindings() {
println!( println!("mode: {mode}, keymodifiers: {modifier}, keycode: {code}, event: {event}");
"mode: {}, keymodifiers: {}, keycode: {}, event: {}",
mode, modifier, code, event
);
} }
} }

View File

@ -30,7 +30,7 @@ fn main() -> io::Result<()> {
let sig = line_editor.read_line(&prompt)?; let sig = line_editor.read_line(&prompt)?;
match sig { match sig {
Signal::Success(buffer) => { Signal::Success(buffer) => {
println!("We processed: {}", buffer); println!("We processed: {buffer}");
} }
Signal::CtrlD | Signal::CtrlC => { Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!"); println!("\nAborted!");

View File

@ -17,9 +17,7 @@ impl Span {
pub fn new(start: usize, end: usize) -> Span { pub fn new(start: usize, end: usize) -> Span {
assert!( assert!(
end >= start, end >= start,
"Can't create a Span whose end < start, start={}, end={}", "Can't create a Span whose end < start, start={start}, end={end}"
start,
end
); );
Span { start, end } Span { start, end }

View File

@ -83,7 +83,7 @@ impl Completer for DefaultCompleter {
if span_line.is_empty() { if span_line.is_empty() {
span_line = s.to_string(); span_line = s.to_string();
} else { } else {
span_line = format!("{} {}", s, span_line); span_line = format!("{s} {span_line}");
} }
if let Some(mut extensions) = self.root.complete(span_line.chars()) { if let Some(mut extensions) = self.root.complete(span_line.chars()) {
extensions.sort(); extensions.sort();
@ -97,7 +97,7 @@ impl Completer for DefaultCompleter {
); );
Suggestion { Suggestion {
value: format!("{}{}", span_line, ext), value: format!("{span_line}{ext}"),
description: None, description: None,
extra: None, extra: None,
span, span,

View File

@ -34,9 +34,7 @@ use {
event::{Event, KeyCode, KeyEvent, KeyModifiers}, event::{Event, KeyCode, KeyEvent, KeyModifiers},
terminal, Result, terminal, Result,
}, },
std::{ std::{fs::File, io, io::Write, process::Command, time::Duration, time::SystemTime},
borrow::Borrow, fs::File, io, io::Write, process::Command, time::Duration, time::SystemTime,
},
}; };
// The POLL_WAIT is used to specify for how long the POLL should wait for // The POLL_WAIT is used to specify for how long the POLL should wait for
@ -1338,7 +1336,7 @@ impl Reedline {
None => Ok(()), None => Ok(()),
Some(BufferEditor { editor, extension }) => { Some(BufferEditor { editor, extension }) => {
let temp_directory = std::env::temp_dir(); let temp_directory = std::env::temp_dir();
let temp_file = temp_directory.join(format!("reedline_buffer.{}", extension)); let temp_file = temp_directory.join(format!("reedline_buffer.{extension}"));
{ {
let mut file = File::create(temp_file.clone())?; let mut file = File::create(temp_file.clone())?;
@ -1425,7 +1423,7 @@ impl Reedline {
.highlight(buffer_to_paint, cursor_position_in_buffer) .highlight(buffer_to_paint, cursor_position_in_buffer)
.render_around_insertion_point( .render_around_insertion_point(
cursor_position_in_buffer, cursor_position_in_buffer,
prompt.render_prompt_multiline_indicator().borrow(), prompt,
self.use_ansi_coloring, self.use_ansi_coloring,
); );

View File

@ -557,10 +557,10 @@ mod tests {
let hfile = histfile.clone(); let hfile = histfile.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
let (mut hist, _) = create_history_at(cap, &hfile); let (mut hist, _) = create_history_at(cap, &hfile);
hist.save(HistoryItem::from_command_line(&format!("A{}", i))) hist.save(HistoryItem::from_command_line(format!("A{i}")))
.unwrap(); .unwrap();
hist.sync().unwrap(); hist.sync().unwrap();
hist.save(HistoryItem::from_command_line(&format!("B{}", i))) hist.save(HistoryItem::from_command_line(format!("B{i}")))
.unwrap(); .unwrap();
}) })
}) })
@ -580,8 +580,8 @@ mod tests {
); );
for i in 0..num_threads { for i in 0..num_threads {
assert!(actual.contains(&format!("A{}", i)),); assert!(actual.contains(&format!("A{i}")),);
assert!(actual.contains(&format!("B{}", i)),); assert!(actual.contains(&format!("B{i}")),);
} }
tmp.close().unwrap(); tmp.close().unwrap();

View File

@ -226,7 +226,7 @@ impl History for FileBackedHistory {
{ {
let mut writer = BufWriter::new(writer_guard.deref_mut()); let mut writer = BufWriter::new(writer_guard.deref_mut());
if truncate { if truncate {
writer.seek(SeekFrom::Start(0))?; writer.rewind()?;
for line in &foreign_entries { for line in &foreign_entries {
writer.write_all(encode_entry(line).as_bytes())?; writer.write_all(encode_entry(line).as_bytes())?;

View File

@ -157,8 +157,7 @@ impl History for SqliteBackedHistory {
fn map_sqlite_err(err: rusqlite::Error) -> ReedlineError { fn map_sqlite_err(err: rusqlite::Error) -> ReedlineError {
// TODO: better error mapping // TODO: better error mapping
ReedlineError(ReedlineErrorVariants::HistoryDatabaseError(format!( ReedlineError(ReedlineErrorVariants::HistoryDatabaseError(format!(
"{:?}", "{err:?}"
err
))) )))
} }
@ -173,10 +172,7 @@ impl SqliteBackedHistory {
pub fn with_file(file: PathBuf) -> Result<Self> { pub fn with_file(file: PathBuf) -> Result<Self> {
if let Some(base_dir) = file.parent() { if let Some(base_dir) = file.parent() {
std::fs::create_dir_all(base_dir).map_err(|e| { std::fs::create_dir_all(base_dir).map_err(|e| {
ReedlineError(ReedlineErrorVariants::HistoryDatabaseError(format!( ReedlineError(ReedlineErrorVariants::HistoryDatabaseError(format!("{e}")))
"{}",
e
)))
})?; })?;
} }
let db = Connection::open(&file).map_err(map_sqlite_err)?; let db = Connection::open(&file).map_err(map_sqlite_err)?;

View File

@ -319,7 +319,7 @@ impl ListMenu {
RESET RESET
) )
} else { } else {
format!("({}) ", desc) format!("({desc}) ")
} }
}); });
@ -339,7 +339,7 @@ impl ListMenu {
let line_str = if index == self.index() { let line_str = if index == self.index() {
format!("{}{}>{}", row_number, description, line.to_uppercase()) format!("{}{}>{}", row_number, description, line.to_uppercase())
} else { } else {
format!("{}{}{}", row_number, description, line) format!("{row_number}{description}{line}")
}; };
// Final string with formatting // Final string with formatting

View File

@ -1,5 +1,8 @@
use nu_ansi_term::Style;
use crate::Prompt;
use super::utils::strip_ansi; use super::utils::strip_ansi;
use nu_ansi_term::{Color, Style};
/// A representation of a buffer with styling, used for doing syntax highlighting /// A representation of a buffer with styling, used for doing syntax highlighting
pub struct StyledText { pub struct StyledText {
@ -34,18 +37,22 @@ impl StyledText {
pub fn render_around_insertion_point( pub fn render_around_insertion_point(
&self, &self,
insertion_point: usize, insertion_point: usize,
multiline_prompt: &str, prompt: &dyn Prompt,
// multiline_prompt: &str,
use_ansi_coloring: bool, use_ansi_coloring: bool,
) -> (String, String) { ) -> (String, String) {
let mut current_idx = 0; let mut current_idx = 0;
let mut left_string = String::new(); let mut left_string = String::new();
let mut right_string = String::new(); let mut right_string = String::new();
let prompt_style = Style::new().fg(Color::LightBlue);
let multiline_prompt = prompt.render_prompt_multiline_indicator();
let prompt_style = Style::new().fg(prompt.get_prompt_multiline_color());
for pair in &self.buffer { for pair in &self.buffer {
if current_idx >= insertion_point { if current_idx >= insertion_point {
right_string.push_str(&render_as_string(pair, &prompt_style, multiline_prompt)); right_string.push_str(&render_as_string(pair, &prompt_style, &multiline_prompt));
} else if pair.1.len() + current_idx <= insertion_point { } else if pair.1.len() + current_idx <= insertion_point {
left_string.push_str(&render_as_string(pair, &prompt_style, multiline_prompt)); left_string.push_str(&render_as_string(pair, &prompt_style, &multiline_prompt));
} else if pair.1.len() + current_idx > insertion_point { } else if pair.1.len() + current_idx > insertion_point {
let offset = insertion_point - current_idx; let offset = insertion_point - current_idx;
@ -55,12 +62,12 @@ impl StyledText {
left_string.push_str(&render_as_string( left_string.push_str(&render_as_string(
&(pair.0, left_side), &(pair.0, left_side),
&prompt_style, &prompt_style,
multiline_prompt, &multiline_prompt,
)); ));
right_string.push_str(&render_as_string( right_string.push_str(&render_as_string(
&(pair.0, right_side), &(pair.0, right_side),
&prompt_style, &prompt_style,
multiline_prompt, &multiline_prompt,
)); ));
} }
current_idx += pair.1.len(); current_idx += pair.1.len();
@ -93,7 +100,7 @@ fn render_as_string(
multiline_prompt: &str, multiline_prompt: &str,
) -> String { ) -> String {
let mut rendered = String::new(); let mut rendered = String::new();
let formatted_multiline_prompt = format!("\n{}", multiline_prompt); let formatted_multiline_prompt = format!("\n{multiline_prompt}");
for (line_number, line) in renderable.1.split('\n').enumerate() { for (line_number, line) in renderable.1.split('\n').enumerate() {
if line_number != 0 { if line_number != 0 {
rendered.push_str(&prompt_style.paint(&formatted_multiline_prompt).to_string()); rendered.push_str(&prompt_style.paint(&formatted_multiline_prompt).to_string());

View File

@ -10,6 +10,7 @@ use {
/// The default color for the prompt, indicator, and right prompt /// The default color for the prompt, indicator, and right prompt
pub static DEFAULT_PROMPT_COLOR: Color = Color::Green; pub static DEFAULT_PROMPT_COLOR: Color = Color::Green;
pub static DEFAULT_PROMPT_MULTILINE_COLOR: nu_ansi_term::Color = nu_ansi_term::Color::LightBlue;
pub static DEFAULT_INDICATOR_COLOR: Color = Color::Cyan; pub static DEFAULT_INDICATOR_COLOR: Color = Color::Cyan;
pub static DEFAULT_PROMPT_RIGHT_COLOR: Color = Color::AnsiValue(5); pub static DEFAULT_PROMPT_RIGHT_COLOR: Color = Color::AnsiValue(5);
@ -79,7 +80,7 @@ impl Display for PromptEditMode {
PromptEditMode::Default => write!(f, "Default"), PromptEditMode::Default => write!(f, "Default"),
PromptEditMode::Emacs => write!(f, "Emacs"), PromptEditMode::Emacs => write!(f, "Emacs"),
PromptEditMode::Vi(_) => write!(f, "Vi_Normal\nVi_Insert"), PromptEditMode::Vi(_) => write!(f, "Vi_Normal\nVi_Insert"),
PromptEditMode::Custom(s) => write!(f, "Custom_{}", s), PromptEditMode::Custom(s) => write!(f, "Custom_{s}"),
} }
} }
} }
@ -105,6 +106,10 @@ pub trait Prompt: Send {
fn get_prompt_color(&self) -> Color { fn get_prompt_color(&self) -> Color {
DEFAULT_PROMPT_COLOR DEFAULT_PROMPT_COLOR
} }
/// Get the default multilince prompt color
fn get_prompt_multiline_color(&self) -> nu_ansi_term::Color {
DEFAULT_PROMPT_MULTILINE_COLOR
}
/// Get the default indicator color /// Get the default indicator color
fn get_indicator_color(&self) -> Color { fn get_indicator_color(&self) -> Color {
DEFAULT_INDICATOR_COLOR DEFAULT_INDICATOR_COLOR

View File

@ -66,7 +66,7 @@ impl Prompt for DefaultPrompt {
PromptViMode::Normal => DEFAULT_VI_NORMAL_PROMPT_INDICATOR.into(), PromptViMode::Normal => DEFAULT_VI_NORMAL_PROMPT_INDICATOR.into(),
PromptViMode::Insert => DEFAULT_VI_INSERT_PROMPT_INDICATOR.into(), PromptViMode::Insert => DEFAULT_VI_INSERT_PROMPT_INDICATOR.into(),
}, },
PromptEditMode::Custom(str) => format!("({})", str).into(), PromptEditMode::Custom(str) => format!("({str})").into(),
} }
} }

View File

@ -79,7 +79,7 @@ pub fn get_reedline_prompt_edit_modes() -> Vec<String> {
/// Return a `Vec<String>` of the Reedline `KeyCode`s /// Return a `Vec<String>` of the Reedline `KeyCode`s
pub fn get_reedline_keycodes() -> Vec<String> { pub fn get_reedline_keycodes() -> Vec<String> {
ReedLineCrossTermKeyCode::iterator() ReedLineCrossTermKeyCode::iterator()
.map(|kc| format!("{}", kc)) .map(|kc| format!("{kc}"))
.collect() .collect()
} }
@ -121,7 +121,7 @@ fn get_keybinding_strings(
mode.to_string(), mode.to_string(),
format!("{:?}", combination.modifier), format!("{:?}", combination.modifier),
format!("{:?}", combination.key_code), format!("{:?}", combination.key_code),
format!("{:?}", event), format!("{event:?}"),
) )
}) })
.collect(); .collect();