mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-02 09:59:46 +08:00
Improve mouse support
Some checks failed
make test / ubuntu (push) Has been cancelled
make test / ubuntu-32bit-static-pcre2 (push) Has been cancelled
make test / ubuntu-asan (push) Has been cancelled
make test / macos (push) Has been cancelled
Rust checks / rustfmt (push) Has been cancelled
Rust checks / clippy (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
Some checks failed
make test / ubuntu (push) Has been cancelled
make test / ubuntu-32bit-static-pcre2 (push) Has been cancelled
make test / ubuntu-asan (push) Has been cancelled
make test / macos (push) Has been cancelled
Rust checks / rustfmt (push) Has been cancelled
Rust checks / clippy (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
This commit is contained in:
parent
a0e687965e
commit
f139d8ebed
|
@ -18,6 +18,7 @@ Interactive improvements
|
|||
when typing a command and :kbd:`enter` while the previous one is still running, the new one will no longer execute immediately. Similarly, keys that are bound to shell commands will be ignored.
|
||||
This mitigates a security issue where a command like ``cat malicious-file.txt`` could write terminal escape codes prompting the terminal to write arbitrary text to fish's standard input.
|
||||
Such a malicious file can still potentially insert arbitrary text into the command line but can no longer execute it directly (:issue:`10987`).
|
||||
- Left mouse click now can select pager items.
|
||||
|
||||
New or improved bindings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
21
src/pager.rs
21
src/pager.rs
|
@ -13,7 +13,7 @@ use crate::future::IsSomeAnd;
|
|||
use crate::highlight::{highlight_shell, HighlightRole, HighlightSpec};
|
||||
use crate::libc::MB_CUR_MAX;
|
||||
use crate::operation_context::OperationContext;
|
||||
use crate::screen::{wcswidth_rendered, wcwidth_rendered, Line, ScreenData};
|
||||
use crate::screen::{wcswidth_rendered, wcwidth_rendered, CharOffset, Line, ScreenData};
|
||||
use crate::termsize::Termsize;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wcstringutil::string_fuzzy_match_string;
|
||||
|
@ -253,9 +253,7 @@ impl Pager {
|
|||
assert!(stop_row <= row_count);
|
||||
assert!(stop_row - start_row <= term_height);
|
||||
// This always printed at the end of the command line.
|
||||
let offset_in_cmdline = usize::MAX;
|
||||
self.completion_print(
|
||||
offset_in_cmdline,
|
||||
cols,
|
||||
&width_by_column,
|
||||
start_row,
|
||||
|
@ -300,7 +298,7 @@ impl Pager {
|
|||
HighlightRole::pager_progress,
|
||||
);
|
||||
print_max(
|
||||
offset_in_cmdline,
|
||||
CharOffset::None,
|
||||
&progress_text,
|
||||
spec,
|
||||
term_width,
|
||||
|
@ -329,7 +327,7 @@ impl Pager {
|
|||
|
||||
let mut search_field_remaining = term_width - 1;
|
||||
search_field_remaining -= print_max(
|
||||
offset_in_cmdline,
|
||||
CharOffset::None,
|
||||
wgettext!(SEARCH_FIELD_PROMPT),
|
||||
HighlightSpec::new(),
|
||||
search_field_remaining,
|
||||
|
@ -337,7 +335,7 @@ impl Pager {
|
|||
search_field,
|
||||
);
|
||||
search_field_remaining -= print_max(
|
||||
offset_in_cmdline,
|
||||
CharOffset::None,
|
||||
&search_field_text,
|
||||
underline,
|
||||
search_field_remaining,
|
||||
|
@ -407,7 +405,6 @@ impl Pager {
|
|||
/// \param lst The list of completions to print
|
||||
fn completion_print(
|
||||
&self,
|
||||
offset_in_cmdline: usize,
|
||||
cols: usize,
|
||||
width_by_column: &[usize; PAGER_MAX_COLS],
|
||||
row_start: usize,
|
||||
|
@ -437,7 +434,7 @@ impl Pager {
|
|||
|
||||
// Print this completion on its own "line".
|
||||
let mut line = self.completion_print_item(
|
||||
offset_in_cmdline,
|
||||
CharOffset::Pager(idx),
|
||||
prefix,
|
||||
el,
|
||||
col_width,
|
||||
|
@ -447,7 +444,7 @@ impl Pager {
|
|||
|
||||
// If there's more to come, append two spaces.
|
||||
if col + 1 < cols {
|
||||
line.append_str(PAGER_SPACER_STRING, HighlightSpec::new(), offset_in_cmdline);
|
||||
line.append_str(PAGER_SPACER_STRING, HighlightSpec::new(), CharOffset::None);
|
||||
}
|
||||
|
||||
// Append this to the real line.
|
||||
|
@ -462,7 +459,7 @@ impl Pager {
|
|||
/// Print the specified item using at the specified amount of space.
|
||||
fn completion_print_item(
|
||||
&self,
|
||||
offset_in_cmdline: usize,
|
||||
offset_in_cmdline: CharOffset,
|
||||
prefix: &wstr,
|
||||
c: &PagerComp,
|
||||
width: usize,
|
||||
|
@ -1100,7 +1097,7 @@ fn divide_round_up(numer: usize, denom: usize) -> usize {
|
|||
/// \param has_more if this flag is true, this is not the entire string, and the string should be
|
||||
/// ellipsized even if the string fits but takes up the whole space.
|
||||
fn print_max_impl(
|
||||
offset_in_cmdline: usize,
|
||||
offset_in_cmdline: CharOffset,
|
||||
s: &wstr,
|
||||
color: impl Fn(usize) -> HighlightSpec,
|
||||
max: usize,
|
||||
|
@ -1136,7 +1133,7 @@ fn print_max_impl(
|
|||
}
|
||||
|
||||
fn print_max(
|
||||
offset_in_cmdline: usize,
|
||||
offset_in_cmdline: CharOffset,
|
||||
s: &wstr,
|
||||
color: HighlightSpec,
|
||||
max: usize,
|
||||
|
|
|
@ -120,7 +120,7 @@ use crate::proc::{
|
|||
print_exit_warning_for_jobs, proc_update_jiffies,
|
||||
};
|
||||
use crate::reader_history_search::{smartcase_flags, ReaderHistorySearch, SearchMode};
|
||||
use crate::screen::{screen_clear, screen_force_clear_to_end, Screen};
|
||||
use crate::screen::{screen_clear, screen_force_clear_to_end, CharOffset, Screen};
|
||||
use crate::signal::{
|
||||
signal_check_cancel, signal_clear_cancel, signal_reset_handlers, signal_set_handlers,
|
||||
signal_set_handlers_once,
|
||||
|
@ -1403,11 +1403,20 @@ impl ReaderData {
|
|||
"; received left mouse click at",
|
||||
click_position
|
||||
);
|
||||
let new_pos = self
|
||||
match self
|
||||
.screen
|
||||
.offset_in_cmdline_given_cursor(click_position, cursor);
|
||||
let (elt, _el) = self.active_edit_line();
|
||||
self.update_buff_pos(elt, Some(new_pos));
|
||||
.offset_in_cmdline_given_cursor(click_position, cursor)
|
||||
{
|
||||
CharOffset::Cmd(new_pos) | CharOffset::Pointer(new_pos) => {
|
||||
let (elt, _el) = self.active_edit_line();
|
||||
self.update_buff_pos(elt, Some(new_pos));
|
||||
}
|
||||
CharOffset::Pager(idx) if self.pager.selected_completion_idx != Some(idx) => {
|
||||
self.pager.selected_completion_idx = Some(idx);
|
||||
self.pager_selection_changed();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,21 @@ use crate::wchar::prelude::*;
|
|||
use crate::wcstringutil::string_prefixes_string;
|
||||
use crate::wutil::fstat;
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub enum CharOffset {
|
||||
#[default]
|
||||
None,
|
||||
Cmd(usize),
|
||||
Pointer(usize),
|
||||
Pager(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct HighlightedChar {
|
||||
highlight: HighlightSpec,
|
||||
character: char,
|
||||
// Logical offset within the command line.
|
||||
offset_in_cmdline: usize,
|
||||
offset_in_cmdline: CharOffset,
|
||||
}
|
||||
|
||||
/// A class representing a single line of a screen.
|
||||
|
@ -70,7 +79,12 @@ impl Line {
|
|||
}
|
||||
|
||||
/// Append a single character `txt` to the line with color `c`.
|
||||
pub fn append(&mut self, character: char, highlight: HighlightSpec, offset_in_cmdline: usize) {
|
||||
pub fn append(
|
||||
&mut self,
|
||||
character: char,
|
||||
highlight: HighlightSpec,
|
||||
offset_in_cmdline: CharOffset,
|
||||
) {
|
||||
self.text.push(HighlightedChar {
|
||||
highlight,
|
||||
character: rendered_character(character),
|
||||
|
@ -79,7 +93,12 @@ impl Line {
|
|||
}
|
||||
|
||||
/// Append a nul-terminated string `txt` to the line, giving each character `color`.
|
||||
pub fn append_str(&mut self, txt: &wstr, highlight: HighlightSpec, offset_in_cmdline: usize) {
|
||||
pub fn append_str(
|
||||
&mut self,
|
||||
txt: &wstr,
|
||||
highlight: HighlightSpec,
|
||||
offset_in_cmdline: CharOffset,
|
||||
) {
|
||||
for c in txt.chars() {
|
||||
self.append(c, highlight, offset_in_cmdline);
|
||||
}
|
||||
|
@ -101,7 +120,7 @@ impl Line {
|
|||
}
|
||||
|
||||
/// Return the logical offset corresponding to this cell
|
||||
pub fn offset_in_cmdline_at(&self, idx: usize) -> usize {
|
||||
pub fn offset_in_cmdline_at(&self, idx: usize) -> CharOffset {
|
||||
self.text[idx].offset_in_cmdline
|
||||
}
|
||||
|
||||
|
@ -338,9 +357,14 @@ impl Screen {
|
|||
self.desired.cursor.y = 0;
|
||||
|
||||
// Append spaces for the left prompt.
|
||||
let prompt_offset = if pager.search_field_shown {
|
||||
CharOffset::None
|
||||
} else {
|
||||
CharOffset::Pointer(0)
|
||||
};
|
||||
for _ in 0..layout.left_prompt_space {
|
||||
let _ = self.desired_append_char(
|
||||
/*offset_in_cmdline=*/ 0,
|
||||
prompt_offset,
|
||||
usize::MAX,
|
||||
' ',
|
||||
HighlightSpec::new(),
|
||||
|
@ -386,11 +410,14 @@ impl Screen {
|
|||
break scrolled_cursor.unwrap();
|
||||
}
|
||||
if !self.desired_append_char(
|
||||
/*offset_in_cmdline=*/
|
||||
if i <= explicit_before_suggestion.len() + layout.autosuggestion.len() {
|
||||
i.min(explicit_before_suggestion.len())
|
||||
if pager.search_field_shown {
|
||||
CharOffset::None
|
||||
} else if i < explicit_before_suggestion.len() {
|
||||
CharOffset::Cmd(i)
|
||||
} else if i < explicit_before_suggestion.len() + layout.autosuggestion.len() {
|
||||
CharOffset::Pointer(explicit_before_suggestion.len())
|
||||
} else {
|
||||
i - layout.autosuggestion.len()
|
||||
CharOffset::Cmd(i - layout.autosuggestion.len())
|
||||
},
|
||||
if is_final_rendering {
|
||||
usize::MAX
|
||||
|
@ -553,7 +580,7 @@ impl Screen {
|
|||
&mut self,
|
||||
viewport_position: ViewportPosition,
|
||||
viewport_cursor: ViewportPosition,
|
||||
) -> usize {
|
||||
) -> CharOffset {
|
||||
let viewport_prompt_y = self.command_line_y_given_cursor_y(viewport_cursor.y);
|
||||
let y = viewport_position
|
||||
.y
|
||||
|
@ -574,14 +601,11 @@ impl Screen {
|
|||
let x = viewport_position.x - viewport_prompt_x;
|
||||
let line = self.actual.line(y);
|
||||
let x = x.max(line.indentation);
|
||||
if x >= line.len() {
|
||||
if self.actual.line_count() == 1 {
|
||||
0
|
||||
} else {
|
||||
line.text.last().unwrap().offset_in_cmdline + 1
|
||||
}
|
||||
} else {
|
||||
line.offset_in_cmdline_at(x)
|
||||
let char = line.text.get(x).or(line.text.last()).unwrap();
|
||||
match char.offset_in_cmdline {
|
||||
CharOffset::Cmd(value) if x >= line.len() => CharOffset::Cmd(value + 1),
|
||||
CharOffset::Pager(_) if x >= line.len() => CharOffset::None,
|
||||
offset => offset,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +730,7 @@ impl Screen {
|
|||
/// automatically handles linebreaks and lines longer than the screen width.
|
||||
fn desired_append_char(
|
||||
&mut self,
|
||||
offset_in_cmdline: usize,
|
||||
offset_in_cmdline: CharOffset,
|
||||
max_y: usize,
|
||||
b: char,
|
||||
c: HighlightSpec,
|
||||
|
|
Loading…
Reference in New Issue
Block a user