reedline/prompt/
default.rs1use crate::{Prompt, PromptEditMode, PromptHistorySearch, PromptHistorySearchStatus, PromptViMode};
2
3use {
4 chrono::Local,
5 std::{borrow::Cow, env},
6};
7
8pub static DEFAULT_PROMPT_INDICATOR: &str = "〉";
10pub static DEFAULT_VI_INSERT_PROMPT_INDICATOR: &str = ": ";
11pub static DEFAULT_VI_NORMAL_PROMPT_INDICATOR: &str = "〉";
12pub static DEFAULT_MULTILINE_INDICATOR: &str = "::: ";
13
14#[derive(Clone)]
18pub struct DefaultPrompt {
19 pub left_prompt: DefaultPromptSegment,
21 pub right_prompt: DefaultPromptSegment,
23}
24
25#[derive(Clone)]
27pub enum DefaultPromptSegment {
28 Basic(String),
30 WorkingDirectory,
32 CurrentDateTime,
34 Empty,
36}
37
38fn render_prompt_segment(prompt: &DefaultPromptSegment) -> Cow<str> {
42 match &prompt {
43 DefaultPromptSegment::Basic(s) => Cow::Borrowed(s),
44 DefaultPromptSegment::WorkingDirectory => {
45 let prompt = get_working_dir().unwrap_or_else(|_| String::from("no path"));
46 Cow::Owned(prompt)
47 }
48 DefaultPromptSegment::CurrentDateTime => Cow::Owned(get_now()),
49 DefaultPromptSegment::Empty => Cow::Borrowed(""),
50 }
51}
52
53impl Prompt for DefaultPrompt {
54 fn render_prompt_left(&self) -> Cow<str> {
55 render_prompt_segment(&self.left_prompt)
56 }
57
58 fn render_prompt_right(&self) -> Cow<str> {
59 render_prompt_segment(&self.right_prompt)
60 }
61
62 fn render_prompt_indicator(&self, edit_mode: PromptEditMode) -> Cow<str> {
63 match edit_mode {
64 PromptEditMode::Default | PromptEditMode::Emacs => DEFAULT_PROMPT_INDICATOR.into(),
65 PromptEditMode::Vi(vi_mode) => match vi_mode {
66 PromptViMode::Normal => DEFAULT_VI_NORMAL_PROMPT_INDICATOR.into(),
67 PromptViMode::Insert => DEFAULT_VI_INSERT_PROMPT_INDICATOR.into(),
68 },
69 PromptEditMode::Custom(str) => format!("({str})").into(),
70 }
71 }
72
73 fn render_prompt_multiline_indicator(&self) -> Cow<str> {
74 Cow::Borrowed(DEFAULT_MULTILINE_INDICATOR)
75 }
76
77 fn render_prompt_history_search_indicator(
78 &self,
79 history_search: PromptHistorySearch,
80 ) -> Cow<str> {
81 let prefix = match history_search.status {
82 PromptHistorySearchStatus::Passing => "",
83 PromptHistorySearchStatus::Failing => "failing ",
84 };
85 Cow::Owned(format!(
88 "({}reverse-search: {}) ",
89 prefix, history_search.term
90 ))
91 }
92}
93
94impl Default for DefaultPrompt {
95 fn default() -> Self {
96 DefaultPrompt {
97 left_prompt: DefaultPromptSegment::WorkingDirectory,
98 right_prompt: DefaultPromptSegment::CurrentDateTime,
99 }
100 }
101}
102
103impl DefaultPrompt {
104 pub const fn new(
108 left_prompt: DefaultPromptSegment,
109 right_prompt: DefaultPromptSegment,
110 ) -> DefaultPrompt {
111 DefaultPrompt {
112 left_prompt,
113 right_prompt,
114 }
115 }
116}
117
118fn get_working_dir() -> Result<String, std::io::Error> {
119 let path = env::current_dir()?;
120 let path_str = path.display().to_string();
121 let homedir: String = match env::var("USERPROFILE") {
122 Ok(win_home) => win_home,
123 Err(_) => match env::var("HOME") {
124 Ok(maclin_home) => maclin_home,
125 Err(_) => path_str.clone(),
126 },
127 };
128 let new_path = if path_str != homedir {
129 path_str.replace(&homedir, "~")
130 } else {
131 path_str
132 };
133 Ok(new_path)
134}
135
136fn get_now() -> String {
137 let now = Local::now();
138 format!("{:>}", now.format("%m/%d/%Y %I:%M:%S %p"))
139}