mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-27 16:51:15 -03:00
committed by
Johannes Altmanninger
parent
ca1d7ef863
commit
231ab22ce4
@@ -5,7 +5,7 @@
|
||||
use crate::input_common::{update_wait_on_escape_ms, update_wait_on_sequence_key_ms};
|
||||
use crate::reader::{
|
||||
reader_change_cursor_end_mode, reader_change_cursor_selection_mode, reader_change_history,
|
||||
reader_schedule_prompt_repaint, reader_set_autosuggestion_enabled,
|
||||
reader_schedule_prompt_repaint, reader_set_autosuggestion_enabled, reader_set_transient_prompt,
|
||||
};
|
||||
use crate::screen::{
|
||||
screen_set_midnight_commander_hack, IS_DUMB, LAYOUT_CACHE_SHARED, ONLY_GRAYSCALE,
|
||||
@@ -73,6 +73,7 @@
|
||||
L!("fish_autosuggestion_enabled"),
|
||||
handle_autosuggestion_change,
|
||||
);
|
||||
table.add_anon(L!("fish_transient_prompt"), handle_transient_prompt_change);
|
||||
table.add_anon(
|
||||
L!("fish_use_posix_spawn"),
|
||||
handle_fish_use_posix_spawn_change,
|
||||
@@ -284,6 +285,10 @@ fn handle_autosuggestion_change(vars: &EnvStack) {
|
||||
reader_set_autosuggestion_enabled(vars);
|
||||
}
|
||||
|
||||
fn handle_transient_prompt_change(vars: &EnvStack) {
|
||||
reader_set_transient_prompt(vars);
|
||||
}
|
||||
|
||||
fn handle_function_path_change(_: &EnvStack) {
|
||||
function::invalidate_path();
|
||||
}
|
||||
|
||||
@@ -320,6 +320,9 @@ pub struct ReaderConfig {
|
||||
/// Whether to allow autosuggestions.
|
||||
pub autosuggest_ok: bool,
|
||||
|
||||
/// Whether to reexecute prompt function before final rendering.
|
||||
pub transient_prompt: bool,
|
||||
|
||||
/// Whether to expand abbreviations.
|
||||
pub expand_abbrev_ok: bool,
|
||||
|
||||
@@ -666,12 +669,13 @@ fn read_i(parser: &Parser) {
|
||||
assert_is_main_thread();
|
||||
parser.assert_can_execute();
|
||||
let mut conf = ReaderConfig::default();
|
||||
conf.event = L!("fish_prompt");
|
||||
conf.complete_ok = true;
|
||||
conf.highlight_ok = true;
|
||||
conf.syntax_check_ok = true;
|
||||
conf.autosuggest_ok = check_autosuggestion_enabled(parser.vars());
|
||||
conf.expand_abbrev_ok = true;
|
||||
conf.event = L!("fish_prompt");
|
||||
conf.autosuggest_ok = check_bool_var(parser.vars(), L!("fish_autosuggestion_enabled"), true);
|
||||
conf.transient_prompt = check_bool_var(parser.vars(), L!("fish_transient_prompt"), false);
|
||||
|
||||
if parser.is_breakpoint() && function::exists(DEBUG_PROMPT_FUNCTION_NAME, parser) {
|
||||
conf.left_prompt_cmd = DEBUG_PROMPT_FUNCTION_NAME.to_owned();
|
||||
@@ -933,25 +937,32 @@ pub fn reader_change_cursor_end_mode(end_mode: CursorEndMode) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_autosuggestion_enabled(vars: &dyn Environment) -> bool {
|
||||
vars.get(L!("fish_autosuggestion_enabled"))
|
||||
fn check_bool_var(vars: &dyn Environment, name: &wstr, default: bool) -> bool {
|
||||
vars.get(name)
|
||||
.map(|v| v.as_string())
|
||||
.map(|v| v != L!("0"))
|
||||
.unwrap_or(true)
|
||||
.unwrap_or(default)
|
||||
}
|
||||
|
||||
/// Enable or disable autosuggestions based on the associated variable.
|
||||
pub fn reader_set_autosuggestion_enabled(vars: &dyn Environment) {
|
||||
// We don't need to _change_ if we're not initialized yet.
|
||||
let Some(data) = current_data() else {
|
||||
return;
|
||||
};
|
||||
let enable = check_autosuggestion_enabled(vars);
|
||||
if data.conf.autosuggest_ok != enable {
|
||||
data.conf.autosuggest_ok = enable;
|
||||
data.force_exec_prompt_and_repaint = true;
|
||||
data.input_data
|
||||
.queue_char(CharEvent::from_readline(ReadlineCmd::Repaint));
|
||||
if let Some(data) = current_data() {
|
||||
let enable = check_bool_var(vars, L!("fish_autosuggestion_enabled"), true);
|
||||
if data.conf.autosuggest_ok != enable {
|
||||
data.conf.autosuggest_ok = enable;
|
||||
data.force_exec_prompt_and_repaint = true;
|
||||
data.input_data
|
||||
.queue_char(CharEvent::from_readline(ReadlineCmd::Repaint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable or disable transient prompt based on the associated variable.
|
||||
pub fn reader_set_transient_prompt(vars: &dyn Environment) {
|
||||
// We don't need to _change_ if we're not initialized yet.
|
||||
if let Some(data) = current_data() {
|
||||
data.conf.transient_prompt = check_bool_var(vars, L!("fish_transient_prompt"), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2220,7 +2231,7 @@ fn readline(&mut self, nchars: Option<NonZeroUsize>) -> Option<WString> {
|
||||
if !self.conf.event.is_empty() {
|
||||
event::fire_generic(self.parser, self.conf.event.to_owned(), vec![]);
|
||||
}
|
||||
self.exec_prompt(true);
|
||||
self.exec_prompt(true, false);
|
||||
|
||||
// Start out as initially dirty.
|
||||
self.force_exec_prompt_and_repaint = true;
|
||||
@@ -2231,6 +2242,10 @@ fn readline(&mut self, nchars: Option<NonZeroUsize>) -> Option<WString> {
|
||||
}
|
||||
}
|
||||
|
||||
if self.conf.transient_prompt {
|
||||
self.exec_prompt(true, true);
|
||||
}
|
||||
|
||||
// Redraw the command line. This is what ensures the autosuggestion is hidden, etc. after the
|
||||
// user presses enter.
|
||||
if self.is_repaint_needed(None)
|
||||
@@ -2736,7 +2751,7 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) {
|
||||
// This can happen e.g. if a variable triggers a repaint,
|
||||
// and the variable is set inside the prompt (#7324).
|
||||
// builtin commandline will refuse to enqueue these.
|
||||
self.exec_prompt(false);
|
||||
self.exec_prompt(false, false);
|
||||
if !self.mode_prompt_buff.is_empty() {
|
||||
if self.is_repaint_needed(None) {
|
||||
self.screen.reset_line(/*repaint_prompt=*/ true);
|
||||
@@ -2747,7 +2762,7 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) {
|
||||
}
|
||||
// Else we repaint as normal.
|
||||
}
|
||||
self.exec_prompt(true);
|
||||
self.exec_prompt(true, false);
|
||||
self.screen.reset_line(/*repaint_prompt=*/ true);
|
||||
self.layout_and_repaint(L!("readline"));
|
||||
self.force_exec_prompt_and_repaint = false;
|
||||
@@ -3853,7 +3868,7 @@ fn clear_screen_and_repaint(&mut self) {
|
||||
self.screen.reset_line(/*repaint_prompt=*/ true);
|
||||
self.layout_and_repaint(L!("readline"));
|
||||
|
||||
self.exec_prompt(true);
|
||||
self.exec_prompt(true, false);
|
||||
self.screen.reset_line(/*repaint_prompt=*/ true);
|
||||
self.layout_and_repaint(L!("readline"));
|
||||
self.force_exec_prompt_and_repaint = false;
|
||||
@@ -4523,14 +4538,23 @@ pub fn reader_write_title(
|
||||
}
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
fn exec_prompt_cmd(&self, prompt_cmd: &wstr) -> Vec<WString> {
|
||||
fn exec_prompt_cmd(&self, prompt_cmd: &wstr, final_prompt: bool) -> Vec<WString> {
|
||||
let mut output = vec![];
|
||||
let _ = exec_subshell(prompt_cmd, self.parser, Some(&mut output), false);
|
||||
if final_prompt && function::exists(prompt_cmd, self.parser) {
|
||||
let _ = exec_subshell(
|
||||
&(prompt_cmd.to_owned() + L!(" --final-rendering")),
|
||||
self.parser,
|
||||
Some(&mut output),
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
let _ = exec_subshell(prompt_cmd, self.parser, Some(&mut output), false);
|
||||
};
|
||||
output
|
||||
}
|
||||
|
||||
/// Execute prompt commands based on the provided arguments. The output is inserted into prompt_buff.
|
||||
fn exec_prompt(&mut self, full_prompt: bool) {
|
||||
fn exec_prompt(&mut self, full_prompt: bool, final_prompt: bool) {
|
||||
// Suppress fish_trace while in the prompt.
|
||||
let _suppress_trace = self.parser.push_scope(|s| s.suppress_fish_trace = true);
|
||||
|
||||
@@ -4545,7 +4569,7 @@ fn exec_prompt(&mut self, full_prompt: bool) {
|
||||
if function::exists(MODE_PROMPT_FUNCTION_NAME, self.parser) {
|
||||
// We do not support multiline mode indicators, so just concatenate all of them.
|
||||
self.mode_prompt_buff =
|
||||
WString::from_iter(self.exec_prompt_cmd(MODE_PROMPT_FUNCTION_NAME));
|
||||
WString::from_iter(self.exec_prompt_cmd(MODE_PROMPT_FUNCTION_NAME, final_prompt));
|
||||
}
|
||||
|
||||
if full_prompt {
|
||||
@@ -4564,7 +4588,12 @@ fn exec_prompt(&mut self, full_prompt: bool) {
|
||||
DEFAULT_PROMPT
|
||||
};
|
||||
|
||||
self.left_prompt_buff = join_strings(&self.exec_prompt_cmd(prompt_cmd), '\n');
|
||||
self.left_prompt_buff =
|
||||
join_strings(&self.exec_prompt_cmd(prompt_cmd, final_prompt), '\n');
|
||||
|
||||
if final_prompt {
|
||||
self.screen.reset_line(true)
|
||||
}
|
||||
}
|
||||
|
||||
// Don't execute the right prompt if it is undefined fish_right_prompt
|
||||
@@ -4573,8 +4602,9 @@ fn exec_prompt(&mut self, full_prompt: bool) {
|
||||
|| function::exists(&self.conf.right_prompt_cmd, self.parser))
|
||||
{
|
||||
// Right prompt does not support multiple lines, so just concatenate all of them.
|
||||
self.right_prompt_buff =
|
||||
WString::from_iter(self.exec_prompt_cmd(&self.conf.right_prompt_cmd));
|
||||
self.right_prompt_buff = WString::from_iter(
|
||||
self.exec_prompt_cmd(&self.conf.right_prompt_cmd, final_prompt),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user