mirror of
https://github.com/apognu/tuigreet.git
synced 2024-11-26 07:28:57 +03:00
Added a submenu to list system-declared sessions (#1).
This commit is contained in:
parent
f2ec800eed
commit
8322386f50
110
Cargo.lock
generated
110
Cargo.lock
generated
@ -1,5 +1,11 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -41,6 +47,15 @@ dependencies = [
|
|||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlv-list"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b391911b9a786312a10cb9d2b3d0735adfd5a8113eb3648de26a75e91b0826c"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
@ -56,6 +71,17 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "greetd_ipc"
|
name = "greetd_ipc"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -67,6 +93,16 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -126,6 +162,22 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-multimap"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e88f947c6799d5eff50e6cf8a2365c17ac4aa8f8f43aceeedc29b616d872a358"
|
||||||
|
dependencies = [
|
||||||
|
"dlv-list",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
@ -144,6 +196,47 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
"rand_hc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.1.56"
|
version = "0.1.56"
|
||||||
@ -159,6 +252,16 @@ dependencies = [
|
|||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-ini"
|
||||||
|
version = "0.15.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a3679dd538c876a7b606f3bb951c8a20fc281a0ff7795f59f7cb490e3f979e1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"ordered-multimap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
@ -281,6 +384,7 @@ dependencies = [
|
|||||||
"getopts",
|
"getopts",
|
||||||
"greetd_ipc",
|
"greetd_ipc",
|
||||||
"nix",
|
"nix",
|
||||||
|
"rust-ini",
|
||||||
"termion",
|
"termion",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
"tui",
|
"tui",
|
||||||
@ -311,6 +415,12 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -14,6 +14,7 @@ nix = "0.17.0"
|
|||||||
textwrap = "0.12.0"
|
textwrap = "0.12.0"
|
||||||
chrono = "0.4.11"
|
chrono = "0.4.11"
|
||||||
zeroize = "1.1.0"
|
zeroize = "1.1.0"
|
||||||
|
rust-ini = "0.15.3"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
@ -28,7 +28,7 @@ The default configuration tends to be as minimal as possible, visually speaking,
|
|||||||
|
|
||||||
The initial prompt container will be 80 column wide. You may change this with `--width` in case you need more space (for example, to account for large PAM challenge messages). Please refer to usage information (`--help`) for more customizaton options.
|
The initial prompt container will be 80 column wide. You may change this with `--width` in case you need more space (for example, to account for large PAM challenge messages). Please refer to usage information (`--help`) for more customizaton options.
|
||||||
|
|
||||||
You may change the command that will be executed after opening a session by huttint `F2` and amending the command.
|
You may change the command that will be executed after opening a session by hittint `F2` and amending the command. Alternatively, you can list the system-declared sessions by hitting `F3`.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ pub enum Mode {
|
|||||||
Username,
|
Username,
|
||||||
Password,
|
Password,
|
||||||
Command,
|
Command,
|
||||||
|
Sessions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Mode {
|
impl Default for Mode {
|
||||||
@ -44,18 +45,25 @@ impl Default for Mode {
|
|||||||
pub struct Greeter {
|
pub struct Greeter {
|
||||||
pub config: Option<Matches>,
|
pub config: Option<Matches>,
|
||||||
pub stream: Option<UnixStream>,
|
pub stream: Option<UnixStream>,
|
||||||
pub command: Option<String>,
|
|
||||||
pub previous_mode: Mode,
|
|
||||||
pub mode: Mode,
|
|
||||||
pub request: Option<Request>,
|
pub request: Option<Request>,
|
||||||
|
|
||||||
|
pub mode: Mode,
|
||||||
|
pub previous_mode: Mode,
|
||||||
pub cursor_offset: i16,
|
pub cursor_offset: i16,
|
||||||
pub username: String,
|
|
||||||
pub answer: String,
|
pub command: Option<String>,
|
||||||
pub new_command: String,
|
pub new_command: String,
|
||||||
pub secret: bool,
|
pub sessions: Vec<(String, String)>,
|
||||||
|
pub selected_session: usize,
|
||||||
|
|
||||||
|
pub username: String,
|
||||||
pub prompt: String,
|
pub prompt: String,
|
||||||
|
pub answer: String,
|
||||||
|
pub secret: bool,
|
||||||
|
|
||||||
pub greeting: Option<String>,
|
pub greeting: Option<String>,
|
||||||
pub message: Option<String>,
|
pub message: Option<String>,
|
||||||
|
|
||||||
pub working: bool,
|
pub working: bool,
|
||||||
pub done: bool,
|
pub done: bool,
|
||||||
}
|
}
|
||||||
@ -72,9 +80,13 @@ impl Drop for Greeter {
|
|||||||
impl Greeter {
|
impl Greeter {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut greeter = Self::default();
|
let mut greeter = Self::default();
|
||||||
|
|
||||||
greeter.parse_options();
|
greeter.parse_options();
|
||||||
|
greeter.sessions = crate::info::get_sessions().unwrap_or_default();
|
||||||
|
greeter.selected_session = greeter.sessions.iter().position(|(_, command)| Some(command) == greeter.command.as_ref()).unwrap_or(0);
|
||||||
greeter
|
greeter
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self) -> &Matches {
|
pub fn config(&self) -> &Matches {
|
||||||
self.config.as_ref().unwrap()
|
self.config.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
31
src/info.rs
31
src/info.rs
@ -1,7 +1,11 @@
|
|||||||
use std::{env, fs};
|
use std::{env, error::Error, fs, path::Path};
|
||||||
|
|
||||||
|
use ini::Ini;
|
||||||
use nix::sys::utsname;
|
use nix::sys::utsname;
|
||||||
|
|
||||||
|
const X_SESSIONS: &str = "/usr/share/xsessions";
|
||||||
|
const WAYLAND_SESSIONS: &str = "/usr/share/wayland-sessions";
|
||||||
|
|
||||||
pub fn get_hostname() -> String {
|
pub fn get_hostname() -> String {
|
||||||
utsname::uname().nodename().to_string()
|
utsname::uname().nodename().to_string()
|
||||||
}
|
}
|
||||||
@ -26,3 +30,28 @@ pub fn get_issue() -> Option<String> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_sessions() -> Result<Vec<(String, String)>, Box<dyn Error>> {
|
||||||
|
let directories = vec![X_SESSIONS, WAYLAND_SESSIONS];
|
||||||
|
|
||||||
|
let files = directories
|
||||||
|
.iter()
|
||||||
|
.flat_map(|directory| fs::read_dir(&directory))
|
||||||
|
.flat_map(|directory| directory.flat_map(|entry| entry.map(|entry| load_desktop_file(entry.path()))).flatten())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_desktop_file<P>(path: P) -> Result<(String, String), Box<dyn Error>>
|
||||||
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let desktop = Ini::load_from_file(path)?;
|
||||||
|
let section = desktop.section(Some("Desktop Entry")).ok_or("no Desktop Entry section in desktop file")?;
|
||||||
|
|
||||||
|
let name = section.get("Name").ok_or("no Name property in desktop file")?;
|
||||||
|
let exec = section.get("Exec").ok_or("no Exec property in desktop file")?;
|
||||||
|
|
||||||
|
Ok((name.to_string(), exec.to_string()))
|
||||||
|
}
|
||||||
|
@ -11,13 +11,10 @@ use crate::{
|
|||||||
pub fn handle(greeter: &mut Greeter, events: &Events) -> Result<(), Box<dyn Error>> {
|
pub fn handle(greeter: &mut Greeter, events: &Events) -> Result<(), Box<dyn Error>> {
|
||||||
if let Event::Input(input) = events.next()? {
|
if let Event::Input(input) = events.next()? {
|
||||||
match input {
|
match input {
|
||||||
Key::Esc => {
|
Key::Esc => match greeter.mode {
|
||||||
if let Mode::Command = greeter.mode {
|
Mode::Command | Mode::Sessions => greeter.mode = greeter.previous_mode,
|
||||||
greeter.mode = greeter.previous_mode;
|
_ => crate::exit(greeter, AuthStatus::Cancel)?,
|
||||||
} else {
|
},
|
||||||
crate::exit(greeter, AuthStatus::Cancel)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Key::Left => greeter.cursor_offset -= 1,
|
Key::Left => greeter.cursor_offset -= 1,
|
||||||
Key::Right => greeter.cursor_offset += 1,
|
Key::Right => greeter.cursor_offset += 1,
|
||||||
@ -28,6 +25,27 @@ pub fn handle(greeter: &mut Greeter, events: &Events) -> Result<(), Box<dyn Erro
|
|||||||
greeter.mode = Mode::Command;
|
greeter.mode = Mode::Command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key::F(3) => {
|
||||||
|
greeter.previous_mode = greeter.mode;
|
||||||
|
greeter.mode = Mode::Sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key::Up => {
|
||||||
|
if let Mode::Sessions = greeter.mode {
|
||||||
|
if greeter.selected_session > 0 {
|
||||||
|
greeter.selected_session -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Key::Down => {
|
||||||
|
if let Mode::Sessions = greeter.mode {
|
||||||
|
if greeter.selected_session < greeter.sessions.len() - 1 {
|
||||||
|
greeter.selected_session += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Key::Ctrl('a') => greeter.cursor_offset = -(greeter.username.len() as i16),
|
Key::Ctrl('a') => greeter.cursor_offset = -(greeter.username.len() as i16),
|
||||||
Key::Ctrl('e') => greeter.cursor_offset = 0,
|
Key::Ctrl('e') => greeter.cursor_offset = 0,
|
||||||
|
|
||||||
@ -52,6 +70,15 @@ pub fn handle(greeter: &mut Greeter, events: &Events) -> Result<(), Box<dyn Erro
|
|||||||
|
|
||||||
Mode::Command => {
|
Mode::Command => {
|
||||||
greeter.command = Some(greeter.new_command.clone());
|
greeter.command = Some(greeter.new_command.clone());
|
||||||
|
greeter.selected_session = greeter.sessions.iter().position(|(_, command)| Some(command) == greeter.command.as_ref()).unwrap_or(0);
|
||||||
|
greeter.mode = greeter.previous_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mode::Sessions => {
|
||||||
|
if let Some((_, command)) = greeter.sessions.get(greeter.selected_session) {
|
||||||
|
greeter.command = Some(command.clone());
|
||||||
|
}
|
||||||
|
|
||||||
greeter.mode = greeter.previous_mode;
|
greeter.mode = greeter.previous_mode;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -72,6 +99,7 @@ fn insert_key(greeter: &mut Greeter, c: char) {
|
|||||||
Mode::Username => &mut greeter.username,
|
Mode::Username => &mut greeter.username,
|
||||||
Mode::Password => &mut greeter.answer,
|
Mode::Password => &mut greeter.answer,
|
||||||
Mode::Command => &mut greeter.new_command,
|
Mode::Command => &mut greeter.new_command,
|
||||||
|
Mode::Sessions => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let index = value.len() as i16 + greeter.cursor_offset;
|
let index = value.len() as i16 + greeter.cursor_offset;
|
||||||
@ -84,6 +112,7 @@ fn delete_key(greeter: &mut Greeter, key: Key) {
|
|||||||
Mode::Username => &mut greeter.username,
|
Mode::Username => &mut greeter.username,
|
||||||
Mode::Password => &mut greeter.answer,
|
Mode::Password => &mut greeter.answer,
|
||||||
Mode::Command => &mut greeter.new_command,
|
Mode::Command => &mut greeter.new_command,
|
||||||
|
Mode::Sessions => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let index = match key {
|
let index = match key {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
mod prompt;
|
mod prompt;
|
||||||
|
mod sessions;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@ -15,9 +16,10 @@ use tui::{
|
|||||||
Terminal,
|
Terminal,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Greeter;
|
use crate::{Greeter, Mode};
|
||||||
|
|
||||||
const EXIT: &str = "Exit";
|
const EXIT: &str = "Exit";
|
||||||
|
const SESSIONS: &str = "Choose session";
|
||||||
const CHANGE_COMMAND: &str = "Change command";
|
const CHANGE_COMMAND: &str = "Change command";
|
||||||
const COMMAND: &str = "COMMAND";
|
const COMMAND: &str = "COMMAND";
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ pub fn draw(terminal: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>, gr
|
|||||||
status_value(EXIT),
|
status_value(EXIT),
|
||||||
status_label("F2"),
|
status_label("F2"),
|
||||||
status_value(CHANGE_COMMAND),
|
status_value(CHANGE_COMMAND),
|
||||||
|
status_label("F3"),
|
||||||
|
status_value(SESSIONS),
|
||||||
status_label(COMMAND),
|
status_label(COMMAND),
|
||||||
status_value(command),
|
status_value(command),
|
||||||
];
|
];
|
||||||
@ -63,7 +67,10 @@ pub fn draw(terminal: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>, gr
|
|||||||
|
|
||||||
f.render_widget(status, chunks[2]);
|
f.render_widget(status, chunks[2]);
|
||||||
|
|
||||||
cursor = self::prompt::draw(greeter, &mut f).ok();
|
cursor = match greeter.mode {
|
||||||
|
Mode::Sessions => self::sessions::draw(greeter, &mut f).ok(),
|
||||||
|
_ => self::prompt::draw(greeter, &mut f).ok(),
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
|
@ -115,10 +115,12 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
|
|||||||
match greeter.mode {
|
match greeter.mode {
|
||||||
Mode::Username => f.render_widget(message, chunks[ANSWER_INDEX]),
|
Mode::Username => f.render_widget(message, chunks[ANSWER_INDEX]),
|
||||||
Mode::Password => f.render_widget(message, chunks[MESSAGE_INDEX]),
|
Mode::Password => f.render_widget(message, chunks[MESSAGE_INDEX]),
|
||||||
Mode::Command => {}
|
Mode::Command | Mode::Sessions => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mode::Sessions => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match greeter.mode {
|
match greeter.mode {
|
||||||
@ -143,6 +145,8 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
|
|||||||
|
|
||||||
Ok((2 + cursor.x + COMMAND.len() as u16 + offset as u16, USERNAME_INDEX as u16 + cursor.y))
|
Ok((2 + cursor.x + COMMAND.len() as u16 + offset as u16, USERNAME_INDEX as u16 + cursor.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mode::Sessions => Ok((1, 1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +158,8 @@ fn get_height(greeter: &Greeter) -> u16 {
|
|||||||
|
|
||||||
let initial = match greeter.mode {
|
let initial = match greeter.mode {
|
||||||
Mode::Username | Mode::Command => (2 * container_padding) + 1,
|
Mode::Username | Mode::Command => (2 * container_padding) + 1,
|
||||||
Mode::Password => (2 * container_padding) + 2 + (2 * prompt_padding),
|
Mode::Password => (2 * container_padding) + prompt_padding + 2,
|
||||||
|
Mode::Sessions => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
match greeter.mode {
|
match greeter.mode {
|
||||||
|
51
src/ui/sessions.rs
Normal file
51
src/ui/sessions.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use std::{error::Error, io};
|
||||||
|
|
||||||
|
use termion::raw::RawTerminal;
|
||||||
|
use tui::{
|
||||||
|
backend::TermionBackend,
|
||||||
|
layout::Rect,
|
||||||
|
style::{Modifier, Style},
|
||||||
|
widgets::{Block, BorderType, Borders, Paragraph, Text},
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::Greeter;
|
||||||
|
|
||||||
|
const CHANGE_SESSION: &str = "Change session";
|
||||||
|
|
||||||
|
pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||||
|
let size = f.size();
|
||||||
|
|
||||||
|
let width = greeter.width();
|
||||||
|
let height: u16 = greeter.sessions.len() as u16 + 4;
|
||||||
|
let x = (size.width - width) / 2;
|
||||||
|
let y = (size.height - height) / 2;
|
||||||
|
|
||||||
|
let container = Rect::new(x, y, width, height);
|
||||||
|
|
||||||
|
let title = format!(" {} ", CHANGE_SESSION);
|
||||||
|
let block = Block::default().title(&title).borders(Borders::ALL).border_type(BorderType::Plain);
|
||||||
|
|
||||||
|
for (index, (name, _)) in greeter.sessions.iter().enumerate() {
|
||||||
|
let frame = Rect::new(x + 2, y + 2 + index as u16, width, 1);
|
||||||
|
let option_text = [get_option(&greeter, name, index)];
|
||||||
|
let option = Paragraph::new(option_text.iter());
|
||||||
|
|
||||||
|
f.render_widget(option, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.render_widget(block, container);
|
||||||
|
|
||||||
|
Ok((1, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_option<'g, S>(greeter: &Greeter, name: S, index: usize) -> Text<'g>
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
if greeter.selected_session == index {
|
||||||
|
Text::styled(name.into(), Style::default().modifier(Modifier::REVERSED))
|
||||||
|
} else {
|
||||||
|
Text::raw(name.into())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user