chore(infra): added clippy check. (#65)
* Added clippy check. * Changed step name. * Used the suggested ci config. * Some more clippy fixes. * Some more clippy fixes. * More clippy fixes. * Removed allow annotations. * Minor lint edit. * More clippy fixes. * Ran cargo fmt. * More clippy fixes. * More clippy fixes. * More clippy fixes. * More clippy fixes. * More clippy fixes. * More clippy fixes. * Code review edits. * Code review edits. * Code review edits. * CI update. * CI update. * CI update. * Added clippy warn so wip won't fail ci. * Cargo fmt.
This commit is contained in:
parent
1586a705d2
commit
9ad7b8a35e
16 changed files with 142 additions and 139 deletions
16
.github/workflows/rust.yml
vendored
16
.github/workflows/rust.yml
vendored
|
|
@ -11,7 +11,7 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
name: Build & test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -23,6 +23,7 @@ jobs:
|
||||||
fmt:
|
fmt:
|
||||||
name: Rustfmt
|
name: Rustfmt
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
|
|
@ -35,4 +36,17 @@ jobs:
|
||||||
with:
|
with:
|
||||||
command: fmt
|
command: fmt
|
||||||
args: --all -- --check
|
args: --all -- --check
|
||||||
|
clippy:
|
||||||
|
name: Clippy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
components: clippy
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --all-features --all-targets
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ use std::sync::mpsc::Sender;
|
||||||
use crate::os_input_output::OsApi;
|
use crate::os_input_output::OsApi;
|
||||||
use crate::pty_bus::PtyInstruction;
|
use crate::pty_bus::PtyInstruction;
|
||||||
use crate::screen::ScreenInstruction;
|
use crate::screen::ScreenInstruction;
|
||||||
use crate::utils::logging::debug_log_to_file;
|
|
||||||
use crate::AppInstruction;
|
use crate::AppInstruction;
|
||||||
use crate::CommandIsExecuting;
|
use crate::CommandIsExecuting;
|
||||||
|
|
||||||
|
|
@ -59,7 +58,8 @@ impl InputHandler {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.buffer = [0; 10];
|
self.buffer = [0; 10];
|
||||||
self.stdin
|
let _ = self
|
||||||
|
.stdin
|
||||||
.read(&mut self.buffer)
|
.read(&mut self.buffer)
|
||||||
.expect("failed to read stdin");
|
.expect("failed to read stdin");
|
||||||
|
|
||||||
|
|
@ -93,7 +93,8 @@ impl InputHandler {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.buffer = [0; 10];
|
self.buffer = [0; 10];
|
||||||
self.stdin
|
let _ = self
|
||||||
|
.stdin
|
||||||
.read(&mut self.buffer)
|
.read(&mut self.buffer)
|
||||||
.expect("failed to read stdin");
|
.expect("failed to read stdin");
|
||||||
// uncomment this to print the entered character to a log file (/tmp/mosaic/mosaic-log.txt) for debugging
|
// uncomment this to print the entered character to a log file (/tmp/mosaic/mosaic-log.txt) for debugging
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ fn split_space(space_to_split: &PositionAndSize, layout: &Layout) -> Vec<Positio
|
||||||
};
|
};
|
||||||
for (i, part) in layout.parts.iter().enumerate() {
|
for (i, part) in layout.parts.iter().enumerate() {
|
||||||
let part_position_and_size = split_parts.get(i).unwrap();
|
let part_position_and_size = split_parts.get(i).unwrap();
|
||||||
if part.parts.len() > 0 {
|
if !part.parts.is_empty() {
|
||||||
let mut part_positions = split_space(&part_position_and_size, part);
|
let mut part_positions = split_space(&part_position_and_size, part);
|
||||||
pane_positions.append(&mut part_positions);
|
pane_positions.append(&mut part_positions);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -114,7 +114,7 @@ fn validate_layout_percentage_total(layout: &Layout) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
for part in layout.parts.iter() {
|
for part in layout.parts.iter() {
|
||||||
if part.parts.len() > 0 {
|
if !part.parts.is_empty() {
|
||||||
return validate_layout_percentage_total(part);
|
return validate_layout_percentage_total(part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,16 +145,14 @@ pub struct Layout {
|
||||||
impl Layout {
|
impl Layout {
|
||||||
pub fn new(layout_path: PathBuf) -> Self {
|
pub fn new(layout_path: PathBuf) -> Self {
|
||||||
let mut layout_file = File::open(&layout_path)
|
let mut layout_file = File::open(&layout_path)
|
||||||
.expect(&format!("cannot find layout {}", &layout_path.display()));
|
.unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display()));
|
||||||
|
|
||||||
let mut layout = String::new();
|
let mut layout = String::new();
|
||||||
layout_file
|
layout_file
|
||||||
.read_to_string(&mut layout)
|
.read_to_string(&mut layout)
|
||||||
.expect(&format!("could not read layout {}", &layout_path.display()));
|
.unwrap_or_else(|_| panic!("could not read layout {}", &layout_path.display()));
|
||||||
let layout: Layout = serde_yaml::from_str(&layout).expect(&format!(
|
let layout: Layout = serde_yaml::from_str(&layout)
|
||||||
"could not parse layout {}",
|
.unwrap_or_else(|_| panic!("could not parse layout {}", &layout_path.display()));
|
||||||
&layout_path.display()
|
|
||||||
));
|
|
||||||
layout.validate();
|
layout.validate();
|
||||||
|
|
||||||
layout
|
layout
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -134,10 +134,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
|
||||||
os_input.clone(),
|
os_input.clone(),
|
||||||
opts.debug,
|
opts.debug,
|
||||||
);
|
);
|
||||||
let maybe_layout = opts.layout.and_then(|layout_path| {
|
let maybe_layout = opts.layout.map(Layout::new);
|
||||||
let layout = Layout::new(layout_path);
|
|
||||||
Some(layout)
|
|
||||||
});
|
|
||||||
|
|
||||||
active_threads.push(
|
active_threads.push(
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
|
|
@ -316,6 +313,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
|
||||||
// This eventually calls the `.init()` method
|
// This eventually calls the `.init()` method
|
||||||
start.call(&[])?;
|
start.call(&[])?;
|
||||||
|
|
||||||
|
#[warn(clippy::never_loop)]
|
||||||
loop {
|
loop {
|
||||||
break;
|
break;
|
||||||
//let (cols, rows) = terminal::size()?;
|
//let (cols, rows) = terminal::size()?;
|
||||||
|
|
@ -377,7 +375,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
|
||||||
match stream {
|
match stream {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
let mut buffer = [0; 65535]; // TODO: more accurate
|
let mut buffer = [0; 65535]; // TODO: more accurate
|
||||||
stream
|
let _ = stream
|
||||||
.read(&mut buffer)
|
.read(&mut buffer)
|
||||||
.expect("failed to parse ipc message");
|
.expect("failed to parse ipc message");
|
||||||
let decoded: ApiCommand = bincode::deserialize(&buffer)
|
let decoded: ApiCommand = bincode::deserialize(&buffer)
|
||||||
|
|
@ -422,7 +420,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
|
||||||
let send_pty_instructions = send_pty_instructions.clone();
|
let send_pty_instructions = send_pty_instructions.clone();
|
||||||
let send_app_instructions = send_app_instructions.clone();
|
let send_app_instructions = send_app_instructions.clone();
|
||||||
let os_input = os_input.clone();
|
let os_input = os_input.clone();
|
||||||
let command_is_executing = command_is_executing.clone();
|
|
||||||
move || {
|
move || {
|
||||||
input_loop(
|
input_loop(
|
||||||
os_input,
|
os_input,
|
||||||
|
|
@ -434,6 +431,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[warn(clippy::never_loop)]
|
||||||
loop {
|
loop {
|
||||||
let app_instruction = receive_app_instructions
|
let app_instruction = receive_app_instructions
|
||||||
.recv()
|
.recv()
|
||||||
|
|
@ -459,7 +457,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
|
||||||
);
|
);
|
||||||
|
|
||||||
os_input.unset_raw_mode(0);
|
os_input.unset_raw_mode(0);
|
||||||
os_input
|
let _ = os_input
|
||||||
.get_stdout_writer()
|
.get_stdout_writer()
|
||||||
.write(goodbye_message.as_bytes())
|
.write(goodbye_message.as_bytes())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,14 @@ use std::env;
|
||||||
fn into_raw_mode(pid: RawFd) {
|
fn into_raw_mode(pid: RawFd) {
|
||||||
let mut tio = tcgetattr(pid).expect("could not get terminal attribute");
|
let mut tio = tcgetattr(pid).expect("could not get terminal attribute");
|
||||||
cfmakeraw(&mut tio);
|
cfmakeraw(&mut tio);
|
||||||
match tcsetattr(pid, SetArg::TCSANOW, &mut tio) {
|
match tcsetattr(pid, SetArg::TCSANOW, &tio) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => panic!("error {:?}", e),
|
Err(e) => panic!("error {:?}", e),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset_raw_mode(pid: RawFd, mut orig_termios: Termios) {
|
fn unset_raw_mode(pid: RawFd, orig_termios: Termios) {
|
||||||
match tcsetattr(pid, SetArg::TCSANOW, &mut orig_termios) {
|
match tcsetattr(pid, SetArg::TCSANOW, &orig_termios) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => panic!("error {:?}", e),
|
Err(e) => panic!("error {:?}", e),
|
||||||
};
|
};
|
||||||
|
|
@ -41,7 +41,7 @@ pub fn get_terminal_size_using_fd(fd: RawFd) -> PositionAndSize {
|
||||||
ws_ypixel: 0,
|
ws_ypixel: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut winsize) };
|
unsafe { ioctl(fd, TIOCGWINSZ, &mut winsize) };
|
||||||
PositionAndSize::from(winsize)
|
PositionAndSize::from(winsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ pub fn set_terminal_size_using_fd(fd: RawFd, columns: u16, rows: u16) {
|
||||||
ws_xpixel: 0,
|
ws_xpixel: 0,
|
||||||
ws_ypixel: 0,
|
ws_ypixel: 0,
|
||||||
};
|
};
|
||||||
unsafe { ioctl(fd, TIOCSWINSZ.into(), &winsize) };
|
unsafe { ioctl(fd, TIOCSWINSZ, &winsize) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_command_exit(mut child: Child) {
|
fn handle_command_exit(mut child: Child) {
|
||||||
|
|
|
||||||
|
|
@ -38,17 +38,17 @@ impl Stream for ReadFromPid {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
if *res == 0 {
|
if *res == 0 {
|
||||||
// indicates end of file
|
// indicates end of file
|
||||||
return Poll::Ready(None);
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
let res = Some(read_buffer[..=*res].to_vec());
|
let res = Some(read_buffer[..=*res].to_vec());
|
||||||
return Poll::Ready(res);
|
Poll::Ready(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e {
|
match e {
|
||||||
nix::Error::Sys(errno) => {
|
nix::Error::Sys(errno) => {
|
||||||
if *errno == nix::errno::Errno::EAGAIN {
|
if *errno == nix::errno::Errno::EAGAIN {
|
||||||
return Poll::Ready(Some(vec![])); // TODO: better with timeout waker somehow
|
Poll::Ready(Some(vec![])) // TODO: better with timeout waker somehow
|
||||||
} else {
|
} else {
|
||||||
Poll::Ready(None)
|
Poll::Ready(None)
|
||||||
}
|
}
|
||||||
|
|
@ -296,12 +296,12 @@ impl PtyBus {
|
||||||
self.id_to_child_pid.insert(pid_primary, pid_secondary);
|
self.id_to_child_pid.insert(pid_primary, pid_secondary);
|
||||||
new_pane_pids.push(pid_primary);
|
new_pane_pids.push(pid_primary);
|
||||||
}
|
}
|
||||||
&self
|
self.send_screen_instructions
|
||||||
.send_screen_instructions
|
|
||||||
.send(ScreenInstruction::ApplyLayout((
|
.send(ScreenInstruction::ApplyLayout((
|
||||||
layout,
|
layout,
|
||||||
new_pane_pids.clone(),
|
new_pane_pids.clone(),
|
||||||
)));
|
)))
|
||||||
|
.unwrap();
|
||||||
for id in new_pane_pids {
|
for id in new_pane_pids {
|
||||||
stream_terminal_bytes(
|
stream_terminal_bytes(
|
||||||
id,
|
id,
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ type BorderAndPaneIds = (usize, Vec<RawFd>);
|
||||||
|
|
||||||
fn split_vertically_with_gap(rect: &PositionAndSize) -> (PositionAndSize, PositionAndSize) {
|
fn split_vertically_with_gap(rect: &PositionAndSize) -> (PositionAndSize, PositionAndSize) {
|
||||||
let width_of_each_half = (rect.columns - 1) / 2;
|
let width_of_each_half = (rect.columns - 1) / 2;
|
||||||
let mut first_rect = rect.clone();
|
let mut first_rect = *rect;
|
||||||
let mut second_rect = rect.clone();
|
let mut second_rect = *rect;
|
||||||
if rect.columns % 2 == 0 {
|
if rect.columns % 2 == 0 {
|
||||||
first_rect.columns = width_of_each_half + 1;
|
first_rect.columns = width_of_each_half + 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -37,8 +37,8 @@ fn split_vertically_with_gap(rect: &PositionAndSize) -> (PositionAndSize, Positi
|
||||||
|
|
||||||
fn split_horizontally_with_gap(rect: &PositionAndSize) -> (PositionAndSize, PositionAndSize) {
|
fn split_horizontally_with_gap(rect: &PositionAndSize) -> (PositionAndSize, PositionAndSize) {
|
||||||
let height_of_each_half = (rect.rows - 1) / 2;
|
let height_of_each_half = (rect.rows - 1) / 2;
|
||||||
let mut first_rect = rect.clone();
|
let mut first_rect = *rect;
|
||||||
let mut second_rect = rect.clone();
|
let mut second_rect = *rect;
|
||||||
if rect.rows % 2 == 0 {
|
if rect.rows % 2 == 0 {
|
||||||
first_rect.rows = height_of_each_half + 1;
|
first_rect.rows = height_of_each_half + 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -98,7 +98,7 @@ impl Screen {
|
||||||
max_panes,
|
max_panes,
|
||||||
send_pty_instructions,
|
send_pty_instructions,
|
||||||
send_app_instructions,
|
send_app_instructions,
|
||||||
full_screen_ws: full_screen_ws.clone(),
|
full_screen_ws: *full_screen_ws,
|
||||||
terminals: BTreeMap::new(),
|
terminals: BTreeMap::new(),
|
||||||
panes_to_hide: HashSet::new(),
|
panes_to_hide: HashSet::new(),
|
||||||
active_terminal: None,
|
active_terminal: None,
|
||||||
|
|
@ -142,7 +142,7 @@ impl Screen {
|
||||||
let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout
|
let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout
|
||||||
let mut new_terminal = TerminalPane::new(
|
let mut new_terminal = TerminalPane::new(
|
||||||
*pid,
|
*pid,
|
||||||
self.full_screen_ws.clone(),
|
self.full_screen_ws,
|
||||||
position_and_size.x,
|
position_and_size.x,
|
||||||
position_and_size.y,
|
position_and_size.y,
|
||||||
);
|
);
|
||||||
|
|
@ -178,7 +178,7 @@ impl Screen {
|
||||||
if self.terminals.is_empty() {
|
if self.terminals.is_empty() {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let new_terminal = TerminalPane::new(pid, self.full_screen_ws.clone(), x, y);
|
let new_terminal = TerminalPane::new(pid, self.full_screen_ws, x, y);
|
||||||
self.os_api.set_terminal_size_using_fd(
|
self.os_api.set_terminal_size_using_fd(
|
||||||
new_terminal.pid,
|
new_terminal.pid,
|
||||||
new_terminal.get_columns() as u16,
|
new_terminal.get_columns() as u16,
|
||||||
|
|
@ -259,7 +259,7 @@ impl Screen {
|
||||||
if self.terminals.is_empty() {
|
if self.terminals.is_empty() {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let new_terminal = TerminalPane::new(pid, self.full_screen_ws.clone(), x, y);
|
let new_terminal = TerminalPane::new(pid, self.full_screen_ws, x, y);
|
||||||
self.os_api.set_terminal_size_using_fd(
|
self.os_api.set_terminal_size_using_fd(
|
||||||
new_terminal.pid,
|
new_terminal.pid,
|
||||||
new_terminal.get_columns() as u16,
|
new_terminal.get_columns() as u16,
|
||||||
|
|
@ -317,7 +317,7 @@ impl Screen {
|
||||||
if self.terminals.is_empty() {
|
if self.terminals.is_empty() {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let new_terminal = TerminalPane::new(pid, self.full_screen_ws.clone(), x, y);
|
let new_terminal = TerminalPane::new(pid, self.full_screen_ws, x, y);
|
||||||
self.os_api.set_terminal_size_using_fd(
|
self.os_api.set_terminal_size_using_fd(
|
||||||
new_terminal.pid,
|
new_terminal.pid,
|
||||||
new_terminal.get_columns() as u16,
|
new_terminal.get_columns() as u16,
|
||||||
|
|
@ -409,10 +409,10 @@ impl Screen {
|
||||||
let active_terminal = &self.get_active_terminal().unwrap();
|
let active_terminal = &self.get_active_terminal().unwrap();
|
||||||
active_terminal
|
active_terminal
|
||||||
.cursor_coordinates()
|
.cursor_coordinates()
|
||||||
.and_then(|(x_in_terminal, y_in_terminal)| {
|
.map(|(x_in_terminal, y_in_terminal)| {
|
||||||
let x = active_terminal.get_x() + x_in_terminal;
|
let x = active_terminal.get_x() + x_in_terminal;
|
||||||
let y = active_terminal.get_y() + y_in_terminal;
|
let y = active_terminal.get_y() + y_in_terminal;
|
||||||
Some((x, y))
|
(x, y)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn toggle_active_terminal_fullscreen(&mut self) {
|
pub fn toggle_active_terminal_fullscreen(&mut self) {
|
||||||
|
|
@ -1427,7 +1427,7 @@ impl Screen {
|
||||||
let terminal_to_close_height = terminal_to_close.get_rows();
|
let terminal_to_close_height = terminal_to_close.get_rows();
|
||||||
if let Some(terminals) = self.terminals_to_the_left_between_aligning_borders(id) {
|
if let Some(terminals) = self.terminals_to_the_left_between_aligning_borders(id) {
|
||||||
for terminal_id in terminals.iter() {
|
for terminal_id in terminals.iter() {
|
||||||
&self.increase_pane_width_right(&terminal_id, terminal_to_close_width + 1);
|
self.increase_pane_width_right(&terminal_id, terminal_to_close_width + 1);
|
||||||
// 1 for the border
|
// 1 for the border
|
||||||
}
|
}
|
||||||
if self.active_terminal == Some(id) {
|
if self.active_terminal == Some(id) {
|
||||||
|
|
@ -1436,7 +1436,7 @@ impl Screen {
|
||||||
} else if let Some(terminals) = self.terminals_to_the_right_between_aligning_borders(id)
|
} else if let Some(terminals) = self.terminals_to_the_right_between_aligning_borders(id)
|
||||||
{
|
{
|
||||||
for terminal_id in terminals.iter() {
|
for terminal_id in terminals.iter() {
|
||||||
&self.increase_pane_width_left(&terminal_id, terminal_to_close_width + 1);
|
self.increase_pane_width_left(&terminal_id, terminal_to_close_width + 1);
|
||||||
// 1 for the border
|
// 1 for the border
|
||||||
}
|
}
|
||||||
if self.active_terminal == Some(id) {
|
if self.active_terminal == Some(id) {
|
||||||
|
|
@ -1444,7 +1444,7 @@ impl Screen {
|
||||||
}
|
}
|
||||||
} else if let Some(terminals) = self.terminals_above_between_aligning_borders(id) {
|
} else if let Some(terminals) = self.terminals_above_between_aligning_borders(id) {
|
||||||
for terminal_id in terminals.iter() {
|
for terminal_id in terminals.iter() {
|
||||||
&self.increase_pane_height_down(&terminal_id, terminal_to_close_height + 1);
|
self.increase_pane_height_down(&terminal_id, terminal_to_close_height + 1);
|
||||||
// 1 for the border
|
// 1 for the border
|
||||||
}
|
}
|
||||||
if self.active_terminal == Some(id) {
|
if self.active_terminal == Some(id) {
|
||||||
|
|
@ -1452,7 +1452,7 @@ impl Screen {
|
||||||
}
|
}
|
||||||
} else if let Some(terminals) = self.terminals_below_between_aligning_borders(id) {
|
} else if let Some(terminals) = self.terminals_below_between_aligning_borders(id) {
|
||||||
for terminal_id in terminals.iter() {
|
for terminal_id in terminals.iter() {
|
||||||
&self.increase_pane_height_up(&terminal_id, terminal_to_close_height + 1);
|
self.increase_pane_height_up(&terminal_id, terminal_to_close_height + 1);
|
||||||
// 1 for the border
|
// 1 for the border
|
||||||
}
|
}
|
||||||
if self.active_terminal == Some(id) {
|
if self.active_terminal == Some(id) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use ::std::fmt::{self, Debug, Formatter};
|
||||||
use crate::terminal_pane::terminal_character::{
|
use crate::terminal_pane::terminal_character::{
|
||||||
CharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER,
|
CharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER,
|
||||||
};
|
};
|
||||||
use crate::utils::logging::{debug_log_to_file, debug_log_to_file_pid_0};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scroll
|
* Scroll
|
||||||
|
|
@ -56,7 +55,7 @@ impl CanonicalLine {
|
||||||
.collect();
|
.collect();
|
||||||
let mut wrapped_fragments = Vec::with_capacity(characters.len() / new_width);
|
let mut wrapped_fragments = Vec::with_capacity(characters.len() / new_width);
|
||||||
|
|
||||||
while characters.len() > 0 {
|
while !characters.is_empty() {
|
||||||
if characters.len() > new_width {
|
if characters.len() > new_width {
|
||||||
wrapped_fragments.push(WrappedFragment::from_vec(
|
wrapped_fragments.push(WrappedFragment::from_vec(
|
||||||
characters.drain(..new_width).collect(),
|
characters.drain(..new_width).collect(),
|
||||||
|
|
@ -65,7 +64,7 @@ impl CanonicalLine {
|
||||||
wrapped_fragments.push(WrappedFragment::from_vec(characters.drain(..).collect()));
|
wrapped_fragments.push(WrappedFragment::from_vec(characters.drain(..).collect()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if wrapped_fragments.len() == 0 {
|
if wrapped_fragments.is_empty() {
|
||||||
wrapped_fragments.push(WrappedFragment::new());
|
wrapped_fragments.push(WrappedFragment::new());
|
||||||
}
|
}
|
||||||
self.wrapped_fragments = wrapped_fragments;
|
self.wrapped_fragments = wrapped_fragments;
|
||||||
|
|
@ -212,7 +211,7 @@ impl CursorPosition {
|
||||||
pub fn move_to_next_canonical_line(&mut self) {
|
pub fn move_to_next_canonical_line(&mut self) {
|
||||||
self.line_index.0 += 1;
|
self.line_index.0 += 1;
|
||||||
}
|
}
|
||||||
pub fn move_to_prev_canonical_line(&mut self) {
|
pub fn _move_to_prev_canonical_line(&mut self) {
|
||||||
self.line_index.0 -= 1;
|
self.line_index.0 -= 1;
|
||||||
}
|
}
|
||||||
pub fn move_to_beginning_of_linewrap(&mut self) {
|
pub fn move_to_beginning_of_linewrap(&mut self) {
|
||||||
|
|
@ -269,37 +268,30 @@ impl Scroll {
|
||||||
}
|
}
|
||||||
pub fn as_character_lines(&self) -> Vec<Vec<TerminalCharacter>> {
|
pub fn as_character_lines(&self) -> Vec<Vec<TerminalCharacter>> {
|
||||||
let mut lines: VecDeque<Vec<TerminalCharacter>> = VecDeque::new(); // TODO: with capacity lines_from_end?
|
let mut lines: VecDeque<Vec<TerminalCharacter>> = VecDeque::new(); // TODO: with capacity lines_from_end?
|
||||||
let mut canonical_lines = self.canonical_lines.iter().rev();
|
let canonical_lines = self.canonical_lines.iter().rev();
|
||||||
let mut lines_to_skip = self.viewport_bottom_offset.unwrap_or(0);
|
let mut lines_to_skip = self.viewport_bottom_offset.unwrap_or(0);
|
||||||
'gather_lines: loop {
|
'gather_lines: for current_canonical_line in canonical_lines {
|
||||||
match canonical_lines.next() {
|
for wrapped_fragment in current_canonical_line.wrapped_fragments.iter().rev() {
|
||||||
Some(current_canonical_line) => {
|
let mut line: Vec<TerminalCharacter> =
|
||||||
for wrapped_fragment in current_canonical_line.wrapped_fragments.iter().rev() {
|
wrapped_fragment.characters.iter().copied().collect();
|
||||||
let mut line: Vec<TerminalCharacter> =
|
if lines_to_skip > 0 {
|
||||||
wrapped_fragment.characters.iter().copied().collect();
|
lines_to_skip -= 1;
|
||||||
if lines_to_skip > 0 {
|
} else {
|
||||||
lines_to_skip -= 1;
|
for _ in line.len()..self.total_columns {
|
||||||
} else {
|
// pad line if needed
|
||||||
for _ in line.len()..self.total_columns {
|
line.push(EMPTY_TERMINAL_CHARACTER);
|
||||||
// pad line if needed
|
|
||||||
line.push(EMPTY_TERMINAL_CHARACTER);
|
|
||||||
}
|
|
||||||
lines.push_front(line);
|
|
||||||
}
|
|
||||||
if lines.len() == self.lines_in_view {
|
|
||||||
break 'gather_lines;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
lines.push_front(line);
|
||||||
|
}
|
||||||
|
if lines.len() == self.lines_in_view {
|
||||||
|
break 'gather_lines;
|
||||||
}
|
}
|
||||||
None => break, // no more lines
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if lines.len() < self.lines_in_view {
|
if lines.len() < self.lines_in_view {
|
||||||
// pad lines in case we don't have enough scrollback to fill the view
|
// pad lines in case we don't have enough scrollback to fill the view
|
||||||
let mut empty_line = vec![];
|
let empty_line = vec![EMPTY_TERMINAL_CHARACTER; self.total_columns];
|
||||||
for _ in 0..self.total_columns {
|
|
||||||
empty_line.push(EMPTY_TERMINAL_CHARACTER);
|
|
||||||
}
|
|
||||||
for _ in lines.len()..self.lines_in_view {
|
for _ in lines.len()..self.lines_in_view {
|
||||||
// pad lines in case we didn't have enough
|
// pad lines in case we didn't have enough
|
||||||
lines.push_back(empty_line.clone());
|
lines.push_back(empty_line.clone());
|
||||||
|
|
@ -358,15 +350,19 @@ impl Scroll {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if current_canonical_line_index == self.canonical_lines.len() - 1 {
|
|
||||||
self.canonical_lines.push(CanonicalLine::new());
|
use std::cmp::Ordering;
|
||||||
self.cursor_position.move_to_next_canonical_line();
|
match current_canonical_line_index.cmp(&(self.canonical_lines.len() - 1)) {
|
||||||
self.cursor_position.move_to_beginning_of_canonical_line();
|
Ordering::Equal => {
|
||||||
} else if current_canonical_line_index < self.canonical_lines.len() - 1 {
|
self.canonical_lines.push(CanonicalLine::new());
|
||||||
self.cursor_position.move_to_next_canonical_line();
|
self.cursor_position.move_to_next_canonical_line();
|
||||||
self.cursor_position.move_to_beginning_of_canonical_line();
|
self.cursor_position.move_to_beginning_of_canonical_line();
|
||||||
} else {
|
}
|
||||||
panic!("cursor out of bounds, cannot add_canonical_line");
|
Ordering::Less => {
|
||||||
|
self.cursor_position.move_to_next_canonical_line();
|
||||||
|
self.cursor_position.move_to_beginning_of_canonical_line();
|
||||||
|
}
|
||||||
|
_ => panic!("cursor out of bounds, cannot add_canonical_line"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn cursor_coordinates_on_screen(&self) -> Option<(usize, usize)> {
|
pub fn cursor_coordinates_on_screen(&self) -> Option<(usize, usize)> {
|
||||||
|
|
@ -378,18 +374,13 @@ impl Scroll {
|
||||||
self.cursor_position.line_index;
|
self.cursor_position.line_index;
|
||||||
let x = self.cursor_position.column_index;
|
let x = self.cursor_position.column_index;
|
||||||
let mut y = 0;
|
let mut y = 0;
|
||||||
let mut indices_and_canonical_lines = self.canonical_lines.iter().enumerate().rev();
|
let indices_and_canonical_lines = self.canonical_lines.iter().enumerate().rev();
|
||||||
loop {
|
for (current_index, current_line) in indices_and_canonical_lines {
|
||||||
match indices_and_canonical_lines.next() {
|
if current_index == canonical_line_cursor_position {
|
||||||
Some((current_index, current_line)) => {
|
y += current_line.wrapped_fragments.len() - line_wrap_cursor_position;
|
||||||
if current_index == canonical_line_cursor_position {
|
break;
|
||||||
y += current_line.wrapped_fragments.len() - line_wrap_cursor_position;
|
} else {
|
||||||
break;
|
y += current_line.wrapped_fragments.len();
|
||||||
} else {
|
|
||||||
y += current_line.wrapped_fragments.len();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => break,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let total_lines = self
|
let total_lines = self
|
||||||
|
|
@ -425,6 +416,7 @@ impl Scroll {
|
||||||
} else {
|
} else {
|
||||||
count
|
count
|
||||||
};
|
};
|
||||||
|
|
||||||
for _ in current_fragment.characters.len()..current_cursor_column_position + move_count {
|
for _ in current_fragment.characters.len()..current_cursor_column_position + move_count {
|
||||||
current_fragment.characters.push(EMPTY_TERMINAL_CHARACTER);
|
current_fragment.characters.push(EMPTY_TERMINAL_CHARACTER);
|
||||||
}
|
}
|
||||||
|
|
@ -441,7 +433,7 @@ impl Scroll {
|
||||||
pub fn move_cursor_to_beginning_of_linewrap(&mut self) {
|
pub fn move_cursor_to_beginning_of_linewrap(&mut self) {
|
||||||
self.cursor_position.move_to_beginning_of_linewrap();
|
self.cursor_position.move_to_beginning_of_linewrap();
|
||||||
}
|
}
|
||||||
pub fn move_cursor_to_beginning_of_canonical_line(&mut self) {
|
pub fn _move_cursor_to_beginning_of_canonical_line(&mut self) {
|
||||||
self.cursor_position.move_to_beginning_of_canonical_line();
|
self.cursor_position.move_to_beginning_of_canonical_line();
|
||||||
}
|
}
|
||||||
pub fn move_cursor_backwards(&mut self, count: usize) {
|
pub fn move_cursor_backwards(&mut self, count: usize) {
|
||||||
|
|
@ -537,6 +529,7 @@ impl Scroll {
|
||||||
.wrapped_fragments
|
.wrapped_fragments
|
||||||
.get_mut(current_line_wrap_position)
|
.get_mut(current_line_wrap_position)
|
||||||
.expect("cursor out of bounds");
|
.expect("cursor out of bounds");
|
||||||
|
|
||||||
for _ in current_fragment.characters.len()..col {
|
for _ in current_fragment.characters.len()..col {
|
||||||
current_fragment.characters.push(EMPTY_TERMINAL_CHARACTER);
|
current_fragment.characters.push(EMPTY_TERMINAL_CHARACTER);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(clippy::clippy::if_same_then_else)]
|
||||||
|
|
||||||
use ::nix::pty::Winsize;
|
use ::nix::pty::Winsize;
|
||||||
use ::std::os::unix::io::RawFd;
|
use ::std::os::unix::io::RawFd;
|
||||||
use ::vte::Perform;
|
use ::vte::Perform;
|
||||||
|
|
@ -285,7 +287,7 @@ impl TerminalPane {
|
||||||
fn move_cursor_backwards(&mut self, count: usize) {
|
fn move_cursor_backwards(&mut self, count: usize) {
|
||||||
self.scroll.move_cursor_backwards(count);
|
self.scroll.move_cursor_backwards(count);
|
||||||
}
|
}
|
||||||
fn reset_all_ansi_codes(&mut self) {
|
fn _reset_all_ansi_codes(&mut self) {
|
||||||
self.pending_styles.clear();
|
self.pending_styles.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -302,15 +304,20 @@ impl vte::Perform for TerminalPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self, byte: u8) {
|
fn execute(&mut self, byte: u8) {
|
||||||
if byte == 13 {
|
match byte {
|
||||||
// 0d, carriage return
|
8 => {
|
||||||
self.move_to_beginning_of_line();
|
// backspace
|
||||||
} else if byte == 08 {
|
self.move_cursor_backwards(1);
|
||||||
// backspace
|
}
|
||||||
self.move_cursor_backwards(1);
|
10 => {
|
||||||
} else if byte == 10 {
|
// 0a, newline
|
||||||
// 0a, newline
|
self.add_newline();
|
||||||
self.add_newline();
|
}
|
||||||
|
13 => {
|
||||||
|
// 0d, carriage return
|
||||||
|
self.move_to_beginning_of_line();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -718,12 +725,9 @@ impl vte::Perform for TerminalPane {
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if first_intermediate_is_questionmark {
|
if first_intermediate_is_questionmark {
|
||||||
match params.get(0) {
|
if let Some(&25) = params.get(0) {
|
||||||
Some(25) => {
|
self.scroll.hide_cursor();
|
||||||
self.scroll.hide_cursor();
|
self.mark_for_rerender();
|
||||||
self.mark_for_rerender();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if c == 'h' {
|
} else if c == 'h' {
|
||||||
|
|
@ -733,12 +737,9 @@ impl vte::Perform for TerminalPane {
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if first_intermediate_is_questionmark {
|
if first_intermediate_is_questionmark {
|
||||||
match params.get(0) {
|
if let Some(&25) = params.get(0) {
|
||||||
Some(25) => {
|
self.scroll.show_cursor();
|
||||||
self.scroll.show_cursor();
|
self.mark_for_rerender();
|
||||||
self.mark_for_rerender();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if c == 'r' {
|
} else if c == 'r' {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::tests::utils::commands::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
||||||
FakeInputOutput::new(fake_win_size.clone())
|
FakeInputOutput::new(*fake_win_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::tests::utils::commands::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
||||||
FakeInputOutput::new(fake_win_size.clone())
|
FakeInputOutput::new(*fake_win_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::tests::utils::commands::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
||||||
FakeInputOutput::new(fake_win_size.clone())
|
FakeInputOutput::new(*fake_win_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::tests::utils::commands::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
||||||
FakeInputOutput::new(fake_win_size.clone())
|
FakeInputOutput::new(*fake_win_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::tests::utils::commands::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
|
||||||
FakeInputOutput::new(fake_win_size.clone())
|
FakeInputOutput::new(*fake_win_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ impl Bytes {
|
||||||
path_to_file.push("tests");
|
path_to_file.push("tests");
|
||||||
path_to_file.push("fixtures");
|
path_to_file.push("fixtures");
|
||||||
path_to_file.push(file_name);
|
path_to_file.push(file_name);
|
||||||
let content =
|
let content = fs::read(path_to_file)
|
||||||
fs::read(path_to_file).expect(&format!("could not read fixture {:?}", &file_name));
|
.unwrap_or_else(|_| panic!("could not read fixture {:?}", &file_name));
|
||||||
Bytes {
|
Bytes {
|
||||||
content,
|
content,
|
||||||
read_position: 0,
|
read_position: 0,
|
||||||
|
|
|
||||||
|
|
@ -30,33 +30,33 @@ pub fn debug_log_to_file(message: String) -> io::Result<()> {
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(MOSAIC_TMP_LOG_FILE)?;
|
.open(MOSAIC_TMP_LOG_FILE)?;
|
||||||
file.write_all(message.as_bytes())?;
|
file.write_all(message.as_bytes())?;
|
||||||
file.write_all("\n".as_bytes())?;
|
file.write_all(b"\n")
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_log_to_file_pid_0(message: String, pid: RawFd) -> io::Result<()> {
|
pub fn debug_log_to_file_pid_0(message: String, pid: RawFd) -> io::Result<()> {
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
debug_log_to_file(message)?;
|
debug_log_to_file(message)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn delete_log_file() -> io::Result<()> {
|
pub fn delete_log_file() -> io::Result<()> {
|
||||||
if fs::metadata(MOSAIC_TMP_LOG_FILE).is_ok() {
|
if fs::metadata(MOSAIC_TMP_LOG_FILE).is_ok() {
|
||||||
fs::remove_file(MOSAIC_TMP_LOG_FILE)?;
|
fs::remove_file(MOSAIC_TMP_LOG_FILE)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn delete_log_dir() -> io::Result<()> {
|
pub fn delete_log_dir() -> io::Result<()> {
|
||||||
if fs::metadata(MOSAIC_TMP_LOG_DIR).is_ok() {
|
if fs::metadata(MOSAIC_TMP_LOG_DIR).is_ok() {
|
||||||
fs::remove_dir_all(MOSAIC_TMP_LOG_DIR)?;
|
fs::remove_dir_all(MOSAIC_TMP_LOG_DIR)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_to_file(message: u8, pid: RawFd) -> io::Result<()> {
|
pub fn debug_to_file(message: u8, pid: RawFd) -> io::Result<()> {
|
||||||
|
|
@ -68,7 +68,5 @@ pub fn debug_to_file(message: u8, pid: RawFd) -> io::Result<()> {
|
||||||
.append(true)
|
.append(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(path)?;
|
.open(path)?;
|
||||||
file.write_all(&[message])?;
|
file.write_all(&[message])
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue