Skip to content

Commit

Permalink
Merge branch 'master' into reset-hunk-#11
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephan Dilly committed Jun 14, 2020
2 parents 25f7ea1 + 0cdaabf commit 8c00238
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- file trees: `arrow-right` on expanded folder moves down into folder
- better scrolling in diff ([#52](https://github.com/extrawurst/gitui/issues/52))
- display current branch in status/log ([#115](https://github.com/extrawurst/gitui/issues/115))
- commit msg popup: add cursor and more controls (`arrow-left/right`, `delete` & `backspace`) [@alistaircarscadden](https://github.com/alistaircarscadden)] ([#46](https://github.com/extrawurst/gitui/issues/46))

### Fixed
- reset file inside folder failed when running `gitui` in a subfolder too ([#118](https://github.com/extrawurst/gitui/issues/118))
Expand Down
1 change: 1 addition & 0 deletions src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,5 @@ where
.border_style(theme.block(focused)),
)
.alignment(Alignment::Left)
.wrap(true)
}
123 changes: 107 additions & 16 deletions src/components/textinput.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ use crate::{
};
use anyhow::Result;
use crossterm::event::{Event, KeyCode, KeyModifiers};
use std::borrow::Cow;
use strings::commands;
use tui::{
backend::Backend,
layout::Rect,
style::Style,
style::Modifier,
widgets::{Clear, Text},
Frame,
};
Expand All @@ -25,6 +24,7 @@ pub struct TextInputComponent {
msg: String,
visible: bool,
theme: Theme,
cursor_position: usize,
}

impl TextInputComponent {
Expand All @@ -40,25 +40,58 @@ impl TextInputComponent {
theme: *theme,
title: title.to_string(),
default_msg: default_msg.to_string(),
cursor_position: 0,
}
}

///
/// Clear the `msg`.
pub fn clear(&mut self) {
self.msg.clear();
}

///
/// Get the `msg`.
pub const fn get_text(&self) -> &String {
&self.msg
}

///
/// Move the cursor right one char.
fn incr_cursor(&mut self) {
if let Some(pos) = self.next_char_position() {
self.cursor_position = pos;
}
}

/// Move the cursor left one char.
fn decr_cursor(&mut self) {
let mut index = self.cursor_position.saturating_sub(1);
while index > 0 && !self.msg.is_char_boundary(index) {
index -= 1;
}
self.cursor_position = index;
}

/// Get the position of the next char, or, if the cursor points
/// to the last char, the `msg.len()`.
/// Returns None when the cursor is already at `msg.len()`.
fn next_char_position(&self) -> Option<usize> {
if self.cursor_position >= self.msg.len() {
return None;
}
let mut index = self.cursor_position.saturating_add(1);
while index < self.msg.len()
&& !self.msg.is_char_boundary(index)
{
index += 1;
}
Some(index)
}

/// Set the `msg`.
pub fn set_text(&mut self, msg: String) {
self.msg = msg;
}

///
/// Set the `title`.
pub fn set_title(&mut self, t: String) {
self.title = t;
}
Expand All @@ -71,16 +104,46 @@ impl DrawableComponent for TextInputComponent {
_rect: Rect,
) -> Result<()> {
if self.visible {
let txt = if self.msg.is_empty() {
[Text::Styled(
Cow::from(self.default_msg.as_str()),
let mut txt: Vec<tui::widgets::Text> = Vec::new();

if self.msg.is_empty() {
txt.push(Text::styled(
self.default_msg.as_str(),
self.theme.text(false, false),
)]
));
} else {
[Text::Styled(
Cow::from(self.msg.clone()),
Style::default(),
)]
let style = self.theme.text(true, false);

// the portion of the text before the cursor is added
// if the cursor is not at the first character
if self.cursor_position > 0 {
txt.push(Text::styled(
&self.msg[..self.cursor_position],
style,
));
}

txt.push(Text::styled(
if let Some(pos) = self.next_char_position() {
&self.msg[self.cursor_position..pos]
} else {
// if the cursor is at the end of the msg
// a whitespace is used to underline
" "
},
style.modifier(Modifier::UNDERLINED),
));

// the final portion of the text is added if there is
// still remaining characters
if let Some(pos) = self.next_char_position() {
if pos < self.msg.len() {
txt.push(Text::styled(
&self.msg[pos..],
style,
));
}
}
};

let area = ui::centered_rect(60, 20, f.size());
Expand Down Expand Up @@ -128,11 +191,39 @@ impl Component for TextInputComponent {
return Ok(true);
}
KeyCode::Char(c) if !is_ctrl => {
self.msg.push(c);
self.msg.insert(self.cursor_position, c);
self.incr_cursor();
return Ok(true);
}
KeyCode::Delete => {
if self.cursor_position < self.msg.len() {
self.msg.remove(self.cursor_position);
}
return Ok(true);
}
KeyCode::Backspace => {
self.msg.pop();
if self.cursor_position > 0 {
self.decr_cursor();
if self.cursor_position < self.msg.len() {
}
self.msg.remove(self.cursor_position);
}
return Ok(true);
}
KeyCode::Left => {
self.decr_cursor();
return Ok(true);
}
KeyCode::Right => {
self.incr_cursor();
return Ok(true);
}
KeyCode::Home => {
self.cursor_position = 0;
return Ok(true);
}
KeyCode::End => {
self.cursor_position = self.msg.len();
return Ok(true);
}
_ => (),
Expand Down

0 comments on commit 8c00238

Please sign in to comment.