Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/ui/prompt.rs')
-rw-r--r--helix-term/src/ui/prompt.rs78
1 files changed, 67 insertions, 11 deletions
diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
index f44020c5..5f9745be 100644
--- a/helix-term/src/ui/prompt.rs
+++ b/helix-term/src/ui/prompt.rs
@@ -30,6 +30,12 @@ pub struct Prompt {
prompt: Cow<'static, str>,
line: String,
cursor: usize,
+ // Fields used for Component callbacks and rendering:
+ line_area: Rect,
+ anchor: usize,
+ truncate_start: bool,
+ truncate_end: bool,
+ // ---
completion: Vec<Completion>,
selection: Option<usize>,
history_register: Option<char>,
@@ -82,6 +88,10 @@ impl Prompt {
prompt,
line: String::new(),
cursor: 0,
+ line_area: Rect::default(),
+ anchor: 0,
+ truncate_start: false,
+ truncate_end: false,
completion: Vec::new(),
selection: None,
history_register,
@@ -389,7 +399,7 @@ impl Prompt {
const BASE_WIDTH: u16 = 30;
impl Prompt {
- pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
+ pub fn render_prompt(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
let theme = &cx.editor.theme;
let prompt_color = theme.get("ui.text");
let completion_color = theme.get("ui.menu");
@@ -499,11 +509,20 @@ impl Prompt {
// render buffer text
surface.set_string(area.x, area.y + line, &self.prompt, prompt_color);
- let line_area = area.clip_left(self.prompt.len() as u16).clip_top(line);
+ self.line_area = area
+ .clip_left(self.prompt.len() as u16)
+ .clip_top(line)
+ .clip_right(2);
+
if self.line.is_empty() {
// Show the most recently entered value as a suggestion.
if let Some(suggestion) = self.first_history_completion(cx.editor) {
- surface.set_string(line_area.x, line_area.y, suggestion, suggestion_color);
+ surface.set_string(
+ self.line_area.x,
+ self.line_area.y,
+ suggestion,
+ suggestion_color,
+ );
}
} else if let Some((language, loader)) = self.language.as_ref() {
let mut text: ui::text::Text = crate::ui::markdown::highlighted_code_block(
@@ -514,9 +533,34 @@ impl Prompt {
None,
)
.into();
- text.render(line_area, surface, cx);
+ text.render(self.line_area, surface, cx);
} else {
- surface.set_string(line_area.x, line_area.y, self.line.clone(), prompt_color);
+ if self.line.len() < self.line_area.width as usize {
+ self.anchor = 0;
+ } else if self.cursor < self.anchor {
+ self.anchor = self.cursor;
+ } else if self.cursor - self.anchor > self.line_area.width as usize {
+ self.anchor = self.cursor - self.line_area.width as usize;
+ }
+
+ self.truncate_start = self.anchor > 0;
+ self.truncate_end = self.line.len() - self.anchor > self.line_area.width as usize;
+
+ // if we keep inserting characters just before the end elipsis, we move the anchor
+ // so that those new characters are displayed
+ if self.truncate_end && self.cursor - self.anchor >= self.line_area.width as usize {
+ self.anchor += 1;
+ }
+
+ surface.set_string_anchored(
+ self.line_area.x,
+ self.line_area.y,
+ self.truncate_start,
+ self.truncate_end,
+ &self.line.as_str()[self.anchor..],
+ self.line_area.width as usize - self.truncate_end as usize,
+ |_| prompt_color,
+ );
}
}
}
@@ -686,14 +730,26 @@ impl Component for Prompt {
}
fn cursor(&self, area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
+ let area = area
+ .clip_left(self.prompt.len() as u16)
+ .clip_right(if self.prompt.len() > 0 { 0 } else { 2 });
+
+ let mut col = area.left() as usize
+ + UnicodeWidthStr::width(&self.line[self.anchor..self.cursor.max(self.anchor)]);
+
+ // ensure the cursor does not go beyond elipses
+ if self.truncate_end && self.cursor - self.anchor >= self.line_area.width as usize {
+ col -= 1;
+ }
+
+ if self.truncate_start && self.cursor == self.anchor {
+ col += 1;
+ }
+
let line = area.height as usize - 1;
+
(
- Some(Position::new(
- area.y as usize + line,
- area.x as usize
- + self.prompt.len()
- + UnicodeWidthStr::width(&self.line[..self.cursor]),
- )),
+ Some(Position::new(area.y as usize + line, col)),
editor.config().cursor_shape.from_mode(Mode::Insert),
)
}