Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: scrollbar #87

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'whiz'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=whiz"
],
"filter": {
"name": "whiz",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'whiz'",
"cargo": {
"args": [
"build",
"--bin=whiz",
"--package=whiz"
],
"filter": {
"name": "whiz",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'whiz'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=whiz",
"--package=whiz"
],
"filter": {
"name": "whiz",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
29 changes: 21 additions & 8 deletions src/actors/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,25 @@ impl CommandActor {

let default_entrypoint = {
#[cfg(not(target_os = "windows"))]
{"bash -c"}
{
"bash -c"
}

#[cfg(target_os = "windows")]
{"cmd /c"}
{
"cmd /c"
}
};

let exec = {
let entrypoint_lex = match &self.entrypoint {
Some(e) => if !e.is_empty() { e.as_str() } else { default_entrypoint },
Some(e) => {
if !e.is_empty() {
e.as_str()
} else {
default_entrypoint
}
}
None => default_entrypoint,
};

Expand All @@ -277,19 +287,22 @@ impl CommandActor {
Some(a) => {
s.push(a.to_owned());
s
},
}
None => s,
}
};

let entrypoint = &entrypoint_split[0];
let nargs: Vec<String> = entrypoint_split[1..]
.to_owned()
.into_iter()
.iter()
.cloned()
.filter(|s| !s.is_empty())
.collect();

self.log_debug(format!("EXEC: {} {:?} at {:?}", entrypoint_lex, nargs, self.cwd));

self.log_debug(format!(
"EXEC: {} {:?} at {:?}",
entrypoint_lex, nargs, self.cwd
));
self.console.do_send(PanelStatus {
panel_name: self.op_name.clone(),
status: None,
Expand Down
88 changes: 77 additions & 11 deletions src/actors/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ use crossterm::{

use super::command::{CommandActor, PoisonPill, Reload};

const DIVIDER_LENGTH: usize = 3; // " | "
const MORE_TABS_LENGTH: usize = 3; // "..."
const BORDER_LENGTH: u16 = 2; // "| " or " |"

pub struct Panel {
logs: Vec<(String, Style)>,
lines: u16,
Expand All @@ -51,6 +55,9 @@ impl Panel {

pub struct ConsoleActor {
terminal: Terminal<CrosstermBackend<io::Stdout>>,
width: u16,
offset: usize,
step: usize,
index: String,
order: Vec<String>,
arbiter: Arbiter,
Expand All @@ -72,6 +79,9 @@ impl ConsoleActor {
let terminal = Terminal::new(backend).unwrap();
Self {
terminal,
width: 0,
offset: 0,
step: 0,
index: order[0].clone(),
order,
arbiter: Arbiter::new(),
Expand All @@ -86,7 +96,6 @@ impl ConsoleActor {
// maximum_scroll is the number of lines
// overflowing in the current focused panel
let maximum_scroll = focused_panel.lines - min(focused_panel.lines, log_height);

// `focused_panel.shift` goes from 0 until maximum_scroll
focused_panel.shift = min(focused_panel.shift + shift, maximum_scroll);
}
Expand All @@ -101,12 +110,52 @@ impl ConsoleActor {
}
}
}

pub fn get_offset(&self) -> usize {
if self.offset > 0 {
self.offset - 1 // first in tabs list "...", skip it
} else {
self.offset
}
}
pub fn get_log_height(&mut self) -> u16 {
let frame = self.terminal.get_frame();
chunks(&frame)[0].height
}

pub fn get_log_width(&mut self) -> u16 {
let frame = self.terminal.get_frame();
chunks(&frame)[0].width
}

pub fn get_visible_tabs(&self) -> (Vec<String>, usize) {
let mut counter: usize = 0;
let mut ret: Vec<String> = Vec::new();
let mut width = (self.width - (BORDER_LENGTH * 2)) as usize;
let mut r = 0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is r required or i can be used to return?

if self.offset > 0 {
ret.push("...".to_string());
width -= MORE_TABS_LENGTH + DIVIDER_LENGTH; // "... | "
}
for i in self.offset..self.order.len() {
r = i;
let tab = self.order[i].clone();
let mut next = 0;
counter += tab.len() + 1; // has "." | "!" | "*"
if i < self.order.len() - 1 {
next = self.order[i + 1].clone().len() + DIVIDER_LENGTH + 1;
}
if counter + DIVIDER_LENGTH + MORE_TABS_LENGTH + next >= width {
ret.push(tab + &" ".repeat(width - MORE_TABS_LENGTH - DIVIDER_LENGTH - counter));
ret.push("...".to_string());
return (ret, r);
} else {
ret.push(tab);
}
counter += DIVIDER_LENGTH;
}
(ret, r)
}

pub fn go_to(&mut self, panel_index: usize) {
if panel_index < self.order.len() {
self.index = self.order[panel_index].clone();
Expand All @@ -121,10 +170,24 @@ impl ConsoleActor {
}

pub fn next(&mut self) {
let idx = self.idx();
let tabs = self.get_visible_tabs().1;
if idx == tabs {
self.offset = 0;
} else if idx + self.step + 1 >= tabs {
self.offset = (self.offset + 1) % self.order.len();
}
self.index = self.order[(self.idx() + 1) % self.order.len()].clone();
}

pub fn previous(&mut self) {
let idx = self.idx();
if idx == 0 {
self.offset = (self.offset + self.order.len() - 1) % self.order.len();
} else if self.offset == 0 && self.idx() <= self.step {
} else if self.idx() as isize - self.step as isize <= self.offset as isize {
self.offset = (self.offset + self.order.len() - 1) % self.order.len();
}
self.index = self.order[(self.idx() + self.order.len() - 1) % self.order.len()].clone();
}

Expand All @@ -139,13 +202,16 @@ impl ConsoleActor {
}

fn draw(&mut self) {
self.width = self.get_log_width();
let idx = self.idx();
let offset = self.get_offset();
let (visible_tabs, length) = self.get_visible_tabs();
self.step = length / 4;
if let Some(focused_panel) = &self.panels.get(&self.index) {
self.terminal
.draw(|f| {
let chunks = chunks(f);
let logs = &focused_panel.logs;

let log_height = chunks[0].height;
let maximum_scroll = focused_panel.lines - min(focused_panel.lines, log_height);

Expand All @@ -164,15 +230,15 @@ impl ConsoleActor {
let paragraph = paragraph
.scroll((maximum_scroll - min(maximum_scroll, focused_panel.shift), 0));
f.render_widget(paragraph, chunks[0]);

let /*mut*/ titles: Vec<Line> = self
.order
let /*mut*/ titles: Vec<Line> = visible_tabs
.iter()
.map(|panel| {
let span = self.panels.get(panel).map(|p| match p.status {
Some(ExitStatus::Exited(0)) => Span::styled(format!("{}.", panel), Style::default().fg(Color::Green)),
Some(_) => Span::styled(format!("{}!", panel), Style::default().fg(Color::Red)),
None => Span::styled(format!("{}*", panel), Style::default()),
let cleared_panel = panel.trim_end().to_string();
let spaces = " ".repeat(panel.len() - cleared_panel.len());
let span = self.panels.get(&cleared_panel).map(|p| match p.status {
Some(ExitStatus::Exited(0)) => Span::styled(format!("{}.{}", cleared_panel, spaces), Style::default().fg(Color::Green)),
Some(_) => Span::styled(format!("{}!{}", cleared_panel, spaces), Style::default().fg(Color::Red)),
None => Span::styled(format!("{}*{}", cleared_panel, spaces), Style::default()),
}).unwrap_or_else(|| Span::styled(panel, Style::default()));
Line::from(span)
})
Expand All @@ -189,7 +255,7 @@ impl ConsoleActor {
*/
let tabs = Tabs::new(titles)
.block(Block::default().borders(Borders::ALL))
.select(idx)
.select(idx - offset)
.highlight_style(
Style::default()
.add_modifier(Modifier::BOLD)
Expand Down
Loading