mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-25 08:47:18 +02:00
Fix horizontal scroll in command window
This commit is contained in:
parent
ce3160a88c
commit
325cdd80c8
1 changed files with 170 additions and 24 deletions
194
src/app.rs
194
src/app.rs
|
@ -350,44 +350,49 @@ impl TaskwarriorTuiApp {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match self.mode {
|
match self.mode {
|
||||||
AppMode::TaskReport => self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks"),
|
AppMode::TaskReport => self.draw_command(
|
||||||
|
f,
|
||||||
|
rects[1],
|
||||||
|
self.filter.as_str(),
|
||||||
|
"Filter Tasks",
|
||||||
|
self.get_position(&self.filter),
|
||||||
|
false,
|
||||||
|
),
|
||||||
AppMode::TaskFilter => {
|
AppMode::TaskFilter => {
|
||||||
let position = self.get_position(&self.filter);
|
let position = self.get_position(&self.filter);
|
||||||
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
|
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
self.draw_command(
|
self.draw_command(
|
||||||
f,
|
f,
|
||||||
rects[1],
|
rects[1],
|
||||||
self.filter.as_str(),
|
self.filter.as_str(),
|
||||||
Span::styled("Filter Tasks", Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled("Filter Tasks", Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
position,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskLog => {
|
AppMode::TaskLog => {
|
||||||
let position = self.get_position(&self.command);
|
let position = self.get_position(&self.command);
|
||||||
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
|
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
self.draw_command(
|
self.draw_command(
|
||||||
f,
|
f,
|
||||||
rects[1],
|
rects[1],
|
||||||
self.command.as_str(),
|
self.command.as_str(),
|
||||||
Span::styled("Log Tasks", Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled("Log Tasks", Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
position,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskSubprocess => {
|
AppMode::TaskSubprocess => {
|
||||||
let position = self.get_position(&self.command);
|
let position = self.get_position(&self.command);
|
||||||
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
|
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
self.draw_command(
|
self.draw_command(
|
||||||
f,
|
f,
|
||||||
rects[1],
|
rects[1],
|
||||||
self.command.as_str(),
|
self.command.as_str(),
|
||||||
Span::styled("Shell Command", Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled("Shell Command", Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
position,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskModify => {
|
AppMode::TaskModify => {
|
||||||
let position = self.get_position(&self.modify);
|
let position = self.get_position(&self.modify);
|
||||||
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
|
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
let label = if task_ids.len() > 1 {
|
let label = if task_ids.len() > 1 {
|
||||||
format!("Modify Tasks {}", task_ids.join(","))
|
format!("Modify Tasks {}", task_ids.join(","))
|
||||||
} else {
|
} else {
|
||||||
|
@ -398,12 +403,12 @@ impl TaskwarriorTuiApp {
|
||||||
rects[1],
|
rects[1],
|
||||||
self.modify.as_str(),
|
self.modify.as_str(),
|
||||||
Span::styled(label, Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled(label, Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
position,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskAnnotate => {
|
AppMode::TaskAnnotate => {
|
||||||
let position = self.get_position(&self.command);
|
let position = self.get_position(&self.command);
|
||||||
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
|
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
let label = if task_ids.len() > 1 {
|
let label = if task_ids.len() > 1 {
|
||||||
format!("Annotate Tasks {}", task_ids.join(","))
|
format!("Annotate Tasks {}", task_ids.join(","))
|
||||||
} else {
|
} else {
|
||||||
|
@ -414,34 +419,51 @@ impl TaskwarriorTuiApp {
|
||||||
rects[1],
|
rects[1],
|
||||||
self.command.as_str(),
|
self.command.as_str(),
|
||||||
Span::styled(label, Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled(label, Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
position,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskAdd => {
|
AppMode::TaskAdd => {
|
||||||
let position = self.get_position(&self.command);
|
let position = self.get_position(&self.command);
|
||||||
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
|
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
self.draw_command(
|
self.draw_command(
|
||||||
f,
|
f,
|
||||||
rects[1],
|
rects[1],
|
||||||
self.command.as_str(),
|
self.command.as_str(),
|
||||||
Span::styled("Add Task", Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled("Add Task", Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
position,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskError => {
|
AppMode::TaskError => {
|
||||||
f.render_widget(Clear, rects[1]);
|
|
||||||
self.draw_command(
|
self.draw_command(
|
||||||
f,
|
f,
|
||||||
rects[1],
|
rects[1],
|
||||||
self.error.as_str(),
|
self.error.as_str(),
|
||||||
Span::styled("Error", Style::default().add_modifier(Modifier::BOLD)),
|
Span::styled("Error", Style::default().add_modifier(Modifier::BOLD)),
|
||||||
|
0,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AppMode::TaskHelpPopup => {
|
AppMode::TaskHelpPopup => {
|
||||||
self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks");
|
self.draw_command(
|
||||||
|
f,
|
||||||
|
rects[1],
|
||||||
|
self.filter.as_str(),
|
||||||
|
"Filter Tasks",
|
||||||
|
self.get_position(&self.filter),
|
||||||
|
false,
|
||||||
|
);
|
||||||
self.draw_help_popup(f, 80, 90);
|
self.draw_help_popup(f, 80, 90);
|
||||||
}
|
}
|
||||||
AppMode::TaskContextMenu => {
|
AppMode::TaskContextMenu => {
|
||||||
self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks");
|
self.draw_command(
|
||||||
|
f,
|
||||||
|
rects[1],
|
||||||
|
self.filter.as_str(),
|
||||||
|
"Filter Tasks",
|
||||||
|
self.get_position(&self.filter),
|
||||||
|
false,
|
||||||
|
);
|
||||||
self.draw_context_menu(f, 80, 50);
|
self.draw_context_menu(f, 80, 50);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -527,16 +549,32 @@ impl TaskwarriorTuiApp {
|
||||||
f.render_stateful_widget(t, area, &mut self.context_table_state);
|
f.render_stateful_widget(t, area, &mut self.context_table_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_command<'a, T>(&self, f: &mut Frame<impl Backend>, rect: Rect, text: &str, title: T)
|
fn draw_command<'a, T>(
|
||||||
where
|
&self,
|
||||||
|
f: &mut Frame<impl Backend>,
|
||||||
|
rect: Rect,
|
||||||
|
text: &str,
|
||||||
|
title: T,
|
||||||
|
position: usize,
|
||||||
|
cursor: bool,
|
||||||
|
) where
|
||||||
T: Into<Spans<'a>>,
|
T: Into<Spans<'a>>,
|
||||||
{
|
{
|
||||||
let p = Paragraph::new(Text::from(text)).block(
|
f.render_widget(Clear, rect);
|
||||||
Block::default()
|
if cursor {
|
||||||
.borders(Borders::ALL)
|
f.set_cursor(
|
||||||
.border_type(BorderType::Rounded)
|
std::cmp::min(rect.x + position as u16 + 1, rect.x + rect.width.saturating_sub(2)),
|
||||||
.title(title.into()),
|
rect.y + 1,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
let p = Paragraph::new(Text::from(text))
|
||||||
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded)
|
||||||
|
.title(title.into()),
|
||||||
|
)
|
||||||
|
.scroll((0, ((position + 3) as u16).saturating_sub(rect.width)));
|
||||||
f.render_widget(p, rect);
|
f.render_widget(p, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2095,6 +2133,7 @@ mod tests {
|
||||||
.task_by_uuid(Uuid::parse_str("3f43831b-88dc-45e2-bf0d-4aea6db634cc").unwrap())
|
.task_by_uuid(Uuid::parse_str("3f43831b-88dc-45e2-bf0d-4aea6db634cc").unwrap())
|
||||||
.is_some());
|
.is_some());
|
||||||
|
|
||||||
|
// test_draw_task_report_with_extended_modify_command();
|
||||||
test_draw_task_report();
|
test_draw_task_report();
|
||||||
test_task_tags();
|
test_task_tags();
|
||||||
test_task_style();
|
test_task_style();
|
||||||
|
@ -2463,6 +2502,113 @@ mod tests {
|
||||||
test_case(&expected);
|
test_case(&expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_draw_task_report_with_extended_modify_command() {
|
||||||
|
let test_case = |expected: &Buffer| {
|
||||||
|
let mut app = TaskwarriorTuiApp::new().unwrap();
|
||||||
|
|
||||||
|
app.task_report_next();
|
||||||
|
app.context_next();
|
||||||
|
|
||||||
|
let total_tasks: u64 = 26;
|
||||||
|
|
||||||
|
assert!(app.get_context().is_ok());
|
||||||
|
assert!(app.update(true).is_ok());
|
||||||
|
assert_eq!(app.tasks.len(), total_tasks as usize);
|
||||||
|
assert_eq!(app.current_context_filter, "");
|
||||||
|
|
||||||
|
let now = Local::now();
|
||||||
|
let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc());
|
||||||
|
|
||||||
|
app.update(true).unwrap();
|
||||||
|
|
||||||
|
let backend = TestBackend::new(50, 15);
|
||||||
|
let mut terminal = Terminal::new(backend).unwrap();
|
||||||
|
app.task_report_show_info = !app.task_report_show_info;
|
||||||
|
terminal
|
||||||
|
.draw(|f| {
|
||||||
|
app.draw(f);
|
||||||
|
app.draw(f);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
app.task_report_show_info = !app.task_report_show_info;
|
||||||
|
terminal
|
||||||
|
.draw(|f| {
|
||||||
|
app.draw(f);
|
||||||
|
app.draw(f);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(terminal.backend().size().unwrap(), expected.area);
|
||||||
|
terminal.backend().assert_buffer(expected);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut expected = Buffer::with_lines(vec![
|
||||||
|
"╭Task|Calendar───────────────────────────────────╮",
|
||||||
|
"│ ID Age Deps P Projec Tag Due Descrip Urg │",
|
||||||
|
"│ │",
|
||||||
|
"│• 27 0s U new ta… 15.00│",
|
||||||
|
"│ 28 0s U none new ta… 15.00│",
|
||||||
|
"╰────────────────────────────────────────────────╯",
|
||||||
|
"╭Task 27─────────────────────────────────────────╮",
|
||||||
|
"│ │",
|
||||||
|
"│Name Value │",
|
||||||
|
"│----------- ------------------------------------│",
|
||||||
|
"│ID 27 │",
|
||||||
|
"╰────────────────────────────────────────────────╯",
|
||||||
|
"╭Filter Tasks────────────────────────────────────╮",
|
||||||
|
"│status:pending -private │",
|
||||||
|
"╰────────────────────────────────────────────────╯",
|
||||||
|
]);
|
||||||
|
|
||||||
|
for i in 1..=4 {
|
||||||
|
// Task
|
||||||
|
expected
|
||||||
|
.get_mut(i, 0)
|
||||||
|
.set_style(Style::default().add_modifier(Modifier::BOLD));
|
||||||
|
}
|
||||||
|
for i in 6..=13 {
|
||||||
|
// Calendar
|
||||||
|
expected
|
||||||
|
.get_mut(i, 0)
|
||||||
|
.set_style(Style::default().add_modifier(Modifier::DIM));
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in &[
|
||||||
|
1..=4, // ID
|
||||||
|
6..=8, // Age
|
||||||
|
10..=13, // Deps
|
||||||
|
15..=15, // P
|
||||||
|
17..=22, // Projec
|
||||||
|
24..=30, // Tag
|
||||||
|
32..=34, // Due
|
||||||
|
36..=42, // Descr
|
||||||
|
44..=48, // Urg
|
||||||
|
] {
|
||||||
|
for i in r.clone().into_iter() {
|
||||||
|
expected
|
||||||
|
.get_mut(i, 1)
|
||||||
|
.set_style(Style::default().add_modifier(Modifier::UNDERLINED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 1..expected.area().width - 1 {
|
||||||
|
expected.get_mut(i, 3).set_style(
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Indexed(1))
|
||||||
|
.bg(Color::Reset)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 1..expected.area().width - 1 {
|
||||||
|
expected
|
||||||
|
.get_mut(i, 4)
|
||||||
|
.set_style(Style::default().fg(Color::Indexed(1)).bg(Color::Indexed(4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
test_case(&expected);
|
||||||
|
}
|
||||||
|
|
||||||
fn test_draw_task_report() {
|
fn test_draw_task_report() {
|
||||||
let test_case = |expected: &Buffer| {
|
let test_case = |expected: &Buffer| {
|
||||||
let mut app = TaskwarriorTuiApp::new().unwrap();
|
let mut app = TaskwarriorTuiApp::new().unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue