created a new struct for a layout without opening a yaml file
This commit is contained in:
parent
a7f509b165
commit
47752720b4
@ -26,5 +26,5 @@ pub struct Opt {
|
|||||||
fn main() {
|
fn main() {
|
||||||
//parse parameter
|
//parse parameter
|
||||||
let opt = Opt::from_args();
|
let opt = Opt::from_args();
|
||||||
ui::Ui::run(&opt);
|
ui::create_ui(&opt);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use std::sync::mpsc;
|
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
|
|
||||||
|
use crate::Opt;
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
use termion::input::TermRead;
|
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
use tui::backend::TermionBackend;
|
use tui::backend::TermionBackend;
|
||||||
use tui::layout::{Constraint, Direction, Layout};
|
use tui::layout::{Constraint, Direction, Layout};
|
||||||
@ -12,7 +11,6 @@ use crate::widget::info;
|
|||||||
use crate::widget::repo_entry;
|
use crate::widget::repo_entry;
|
||||||
use crate::widget::service_switcher;
|
use crate::widget::service_switcher;
|
||||||
use crate::widget::tag_list;
|
use crate::widget::tag_list;
|
||||||
use crate::Opt;
|
|
||||||
|
|
||||||
pub struct Ui {
|
pub struct Ui {
|
||||||
state: State,
|
state: State,
|
||||||
@ -56,7 +54,7 @@ impl Ui {
|
|||||||
state: State::SelectService,
|
state: State::SelectService,
|
||||||
repo: repo_entry::RepoEntry::new(repo_id),
|
repo: repo_entry::RepoEntry::new(repo_id),
|
||||||
tags: tag_list::TagList::with_status("Tags are empty"),
|
tags: tag_list::TagList::with_status("Tags are empty"),
|
||||||
services: service_switcher::ServiceSwitcher::new(&opt.config),
|
services: service_switcher::ServiceSwitcher::new(&opt.config).unwrap(),
|
||||||
info: info::Info::new("Select image of edit Repository"),
|
info: info::Info::new("Select image of edit Repository"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,7 +68,7 @@ impl Ui {
|
|||||||
let mut terminal = Terminal::new(backend).unwrap();
|
let mut terminal = Terminal::new(backend).unwrap();
|
||||||
|
|
||||||
//setup input thread
|
//setup input thread
|
||||||
let receiver = ui.spawn_stdin_channel();
|
let receiver = super::spawn_stdin_channel();
|
||||||
|
|
||||||
//core interaction loop
|
//core interaction loop
|
||||||
'core: loop {
|
'core: loop {
|
||||||
@ -212,18 +210,4 @@ impl Ui {
|
|||||||
|
|
||||||
terminal.clear().unwrap();
|
terminal.clear().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// create a thread for catching input and send them to core loop
|
|
||||||
pub fn spawn_stdin_channel(&self) -> mpsc::Receiver<termion::event::Key> {
|
|
||||||
let (tx, rx) = mpsc::channel::<termion::event::Key>();
|
|
||||||
|
|
||||||
thread::spawn(move || loop {
|
|
||||||
let stdin = io::stdin();
|
|
||||||
for c in stdin.keys() {
|
|
||||||
tx.send(c.unwrap()).unwrap();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
thread::sleep(std::time::Duration::from_millis(64));
|
|
||||||
rx
|
|
||||||
}
|
|
||||||
}
|
}
|
32
src/ui/mod.rs
Normal file
32
src/ui/mod.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
mod default;
|
||||||
|
mod no_yaml;
|
||||||
|
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
|
use crate::Opt;
|
||||||
|
use termion::input::TermRead;
|
||||||
|
|
||||||
|
use crate::widget::service_switcher;
|
||||||
|
|
||||||
|
pub fn create_ui(opt: &Opt) {
|
||||||
|
let service_result = service_switcher::ServiceSwitcher::new(&opt.config);
|
||||||
|
match service_result {
|
||||||
|
None => no_yaml::NoYaml::run(opt),
|
||||||
|
Some(_) => default::Ui::run(opt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// create a thread for catching input and send them to core loop
|
||||||
|
pub fn spawn_stdin_channel() -> mpsc::Receiver<termion::event::Key> {
|
||||||
|
let (tx, rx) = mpsc::channel::<termion::event::Key>();
|
||||||
|
|
||||||
|
thread::spawn(move || loop {
|
||||||
|
let stdin = io::stdin();
|
||||||
|
for c in stdin.keys() {
|
||||||
|
tx.send(c.unwrap()).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread::sleep(std::time::Duration::from_millis(64));
|
||||||
|
rx
|
||||||
|
}
|
138
src/ui/no_yaml.rs
Normal file
138
src/ui/no_yaml.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
|
use termion::event::Key;
|
||||||
|
use termion::raw::IntoRawMode;
|
||||||
|
use tui::backend::TermionBackend;
|
||||||
|
use tui::layout::{Constraint, Direction, Layout};
|
||||||
|
use tui::Terminal;
|
||||||
|
|
||||||
|
use crate::widget::info;
|
||||||
|
use crate::widget::repo_entry;
|
||||||
|
use crate::widget::tag_list;
|
||||||
|
use crate::Opt;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
|
pub enum State {
|
||||||
|
EditRepo,
|
||||||
|
SelectTag,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::iter::Iterator for State {
|
||||||
|
type Item = Self;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self {
|
||||||
|
State::EditRepo => *self = State::SelectTag,
|
||||||
|
State::SelectTag => *self = State::EditRepo,
|
||||||
|
}
|
||||||
|
Some(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoYaml {
|
||||||
|
state: State,
|
||||||
|
repo: repo_entry::RepoEntry,
|
||||||
|
tags: tag_list::TagList,
|
||||||
|
info: info::Info,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoYaml {
|
||||||
|
pub fn run(opt: &Opt) {
|
||||||
|
let (repo, load_repo) = match &opt.repo {
|
||||||
|
None => (
|
||||||
|
repo_entry::RepoEntry::new(
|
||||||
|
"enter a repository or select one from docker-compose.yml",
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
Some(repo_id) => (repo_entry::RepoEntry::new(repo_id), true),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut ui = NoYaml {
|
||||||
|
state: State::EditRepo,
|
||||||
|
repo,
|
||||||
|
tags: tag_list::TagList::with_status("Tags are empty"),
|
||||||
|
info: info::Info::new("edit the Repository widget to load tags"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// load tags if a repository was given thorugh paramter
|
||||||
|
if load_repo {
|
||||||
|
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup tui
|
||||||
|
let stdout = io::stdout().into_raw_mode().unwrap();
|
||||||
|
let backend = TermionBackend::new(stdout);
|
||||||
|
let mut terminal = Terminal::new(backend).unwrap();
|
||||||
|
|
||||||
|
//setup input thread
|
||||||
|
let receiver = super::spawn_stdin_channel();
|
||||||
|
|
||||||
|
//core interaction loop
|
||||||
|
'core: loop {
|
||||||
|
//draw
|
||||||
|
terminal
|
||||||
|
.draw(|rect| {
|
||||||
|
let chunks = Layout::default()
|
||||||
|
.direction(Direction::Vertical)
|
||||||
|
.constraints(
|
||||||
|
[
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Min(7),
|
||||||
|
Constraint::Length(2),
|
||||||
|
]
|
||||||
|
.as_ref(),
|
||||||
|
)
|
||||||
|
.split(rect.size());
|
||||||
|
|
||||||
|
rect.render_widget(ui.repo.render(ui.state == State::EditRepo), chunks[0]);
|
||||||
|
let (list, state) = ui.tags.render(ui.state == State::SelectTag);
|
||||||
|
rect.render_stateful_widget(list, chunks[1], state);
|
||||||
|
rect.render_widget(ui.info.render(), chunks[2]);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
//handle input
|
||||||
|
match receiver.try_recv() {
|
||||||
|
Ok(Key::Ctrl('q')) => break 'core,
|
||||||
|
Ok(Key::Char('\t')) => {
|
||||||
|
ui.state.next();
|
||||||
|
}
|
||||||
|
Ok(Key::Ctrl('r')) => {
|
||||||
|
ui.repo.confirm();
|
||||||
|
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
||||||
|
}
|
||||||
|
Ok(Key::Ctrl('n')) => match ui.tags.next_page() {
|
||||||
|
Err(e) => ui.info.set_info(&format!("{}", e)),
|
||||||
|
Ok(_) => (),
|
||||||
|
},
|
||||||
|
Ok(Key::Ctrl('p')) => match ui.tags.prev_page() {
|
||||||
|
Err(e) => ui.info.set_info(&format!("{}", e)),
|
||||||
|
Ok(_) => (),
|
||||||
|
},
|
||||||
|
Ok(Key::Char('\n')) => match ui.state {
|
||||||
|
State::EditRepo => {
|
||||||
|
ui.repo.confirm();
|
||||||
|
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
Ok(Key::Char(key)) => match ui.state {
|
||||||
|
State::EditRepo => {
|
||||||
|
ui.info.set_info("Editing Repository");
|
||||||
|
ui.repo.handle_input(Key::Char(key));
|
||||||
|
}
|
||||||
|
State::SelectTag => {
|
||||||
|
ui.tags.handle_input(Key::Char(key));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
//sleep for 32ms (30 fps)
|
||||||
|
thread::sleep(std::time::Duration::from_millis(32));
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.clear().unwrap();
|
||||||
|
}
|
||||||
|
}
|
@ -3,8 +3,6 @@ use tui::layout::Alignment;
|
|||||||
use tui::style::{Color, Style};
|
use tui::style::{Color, Style};
|
||||||
use tui::widgets::{Block, Borders, Paragraph};
|
use tui::widgets::{Block, Borders, Paragraph};
|
||||||
|
|
||||||
use crate::ui::State;
|
|
||||||
|
|
||||||
pub struct RepoEntry {
|
pub struct RepoEntry {
|
||||||
text: String,
|
text: String,
|
||||||
old_text: String,
|
old_text: String,
|
||||||
|
@ -9,7 +9,6 @@ use tui::style::{Color, Style};
|
|||||||
use tui::widgets::{Block, Borders, List, ListState};
|
use tui::widgets::{Block, Borders, List, ListState};
|
||||||
|
|
||||||
use crate::repo;
|
use crate::repo;
|
||||||
use crate::ui::State;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -34,7 +33,7 @@ pub struct ServiceSwitcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceSwitcher {
|
impl ServiceSwitcher {
|
||||||
pub fn new(file: &Option<PathBuf>) -> Self {
|
pub fn new(file: &Option<PathBuf>) -> Option<Self> {
|
||||||
let mut file_list = vec![
|
let mut file_list = vec![
|
||||||
PathBuf::from("docker-compose.yml"),
|
PathBuf::from("docker-compose.yml"),
|
||||||
PathBuf::from("docker-compose.yaml"),
|
PathBuf::from("docker-compose.yaml"),
|
||||||
@ -55,21 +54,16 @@ impl ServiceSwitcher {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Self {
|
return Some(Self {
|
||||||
list,
|
list,
|
||||||
state: ListState::default(),
|
state: ListState::default(),
|
||||||
changed: false,
|
changed: false,
|
||||||
opened_file: file,
|
opened_file: file,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//could not find docker-compose file
|
//could not find docker-compose file
|
||||||
Self {
|
None
|
||||||
list: vec![format!("No docker-compose file found")],
|
|
||||||
state: ListState::default(),
|
|
||||||
changed: false,
|
|
||||||
opened_file: PathBuf::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, colored: bool) -> (List, &mut ListState) {
|
pub fn render(&mut self, colored: bool) -> (List, &mut ListState) {
|
||||||
|
@ -5,7 +5,6 @@ use tui::style::{Color, Style};
|
|||||||
use tui::widgets::{Block, Borders, List, ListState};
|
use tui::widgets::{Block, Borders, List, ListState};
|
||||||
|
|
||||||
use crate::tags;
|
use crate::tags;
|
||||||
use crate::ui::State;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
Loading…
Reference in New Issue
Block a user