ui: add window title config option
Use xterm window title escape sequences to set window title when launched and restoring the previous one when exiting. If option is blank, no title setting occurs.embed
parent
ccc58860e6
commit
205ebe2f1c
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use super::deserializers::non_empty_string;
|
||||
|
||||
/// Settings for terminal display
|
||||
#[derive(Debug, Deserialize, Clone, Serialize)]
|
||||
#[serde(default)]
|
||||
|
@ -26,6 +28,8 @@ pub struct TerminalSettings {
|
|||
/// light, dark
|
||||
pub theme: String,
|
||||
pub ascii_drawing: bool,
|
||||
#[serde(deserialize_with = "non_empty_string")]
|
||||
pub window_title: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for TerminalSettings {
|
||||
|
@ -33,6 +37,7 @@ impl Default for TerminalSettings {
|
|||
TerminalSettings {
|
||||
theme: "dark".to_string(),
|
||||
ascii_drawing: false,
|
||||
window_title: Some("meli".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ use std::result;
|
|||
use std::thread;
|
||||
use termion::raw::IntoRawMode;
|
||||
use termion::screen::AlternateScreen;
|
||||
use termion::{clear, cursor, style};
|
||||
use termion::{clear, cursor};
|
||||
|
||||
pub type StateStdout = termion::screen::AlternateScreen<termion::raw::RawTerminal<std::io::Stdout>>;
|
||||
|
||||
|
@ -142,17 +142,7 @@ pub struct State {
|
|||
impl Drop for State {
|
||||
fn drop(&mut self) {
|
||||
// When done, restore the defaults to avoid messing with the terminal.
|
||||
write!(
|
||||
self.stdout(),
|
||||
"{}{}{}{}{}",
|
||||
clear::All,
|
||||
style::Reset,
|
||||
cursor::Goto(1, 1),
|
||||
cursor::Show,
|
||||
BracketModeEnd,
|
||||
)
|
||||
.unwrap();
|
||||
self.flush();
|
||||
self.switch_to_main_screen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,15 +192,11 @@ impl State {
|
|||
.collect();
|
||||
accounts.sort_by(|a, b| a.name().cmp(&b.name()));
|
||||
|
||||
let _stdout = std::io::stdout();
|
||||
_stdout.lock();
|
||||
let stdout = AlternateScreen::from(_stdout.into_raw_mode().unwrap());
|
||||
|
||||
let mut s = State {
|
||||
cols,
|
||||
rows,
|
||||
grid: CellBuffer::new(cols, rows, Cell::with_char(' ')),
|
||||
stdout: Some(stdout),
|
||||
stdout: None,
|
||||
child: None,
|
||||
mode: UIMode::Normal,
|
||||
components: Vec::with_capacity(1),
|
||||
|
@ -249,16 +235,7 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
write!(
|
||||
s.stdout(),
|
||||
"{}{}{}{}",
|
||||
BracketModeStart,
|
||||
cursor::Hide,
|
||||
clear::All,
|
||||
cursor::Goto(1, 1)
|
||||
)
|
||||
.unwrap();
|
||||
s.flush();
|
||||
s.switch_to_alternate_screen();
|
||||
debug!("inserting mailbox hashes:");
|
||||
{
|
||||
/* Account::watch() needs
|
||||
|
@ -285,7 +262,7 @@ impl State {
|
|||
account.watch((work_controller, sender, replies));
|
||||
}
|
||||
}
|
||||
s.restore_input();
|
||||
s.context.restore_input();
|
||||
s
|
||||
}
|
||||
|
||||
|
@ -338,29 +315,41 @@ impl State {
|
|||
pub fn switch_to_main_screen(&mut self) {
|
||||
write!(
|
||||
self.stdout(),
|
||||
"{}{}",
|
||||
"{}{}{}{}",
|
||||
termion::screen::ToMainScreen,
|
||||
cursor::Show
|
||||
cursor::Show,
|
||||
RestoreWindowTitleIconFromStack,
|
||||
BracketModeEnd,
|
||||
)
|
||||
.unwrap();
|
||||
self.flush();
|
||||
self.stdout = None;
|
||||
self.context.input.kill();
|
||||
}
|
||||
|
||||
pub fn switch_to_alternate_screen(&mut self) {
|
||||
let s = std::io::stdout();
|
||||
s.lock();
|
||||
self.stdout = Some(AlternateScreen::from(s.into_raw_mode().unwrap()));
|
||||
|
||||
let mut stdout = AlternateScreen::from(s.into_raw_mode().unwrap());
|
||||
|
||||
write!(
|
||||
self.stdout(),
|
||||
"{}{}{}{}",
|
||||
&mut stdout,
|
||||
"{save_title_to_stack}{}{}{}{window_title}{}{}",
|
||||
termion::screen::ToAlternateScreen,
|
||||
cursor::Hide,
|
||||
clear::All,
|
||||
cursor::Goto(1, 1)
|
||||
cursor::Goto(1, 1),
|
||||
BracketModeStart,
|
||||
save_title_to_stack = SaveWindowTitleIconToStack,
|
||||
window_title = if let Some(ref title) = self.context.settings.terminal.window_title {
|
||||
format!("\x1b]2;{}\x07", title)
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
self.stdout = Some(stdout);
|
||||
self.flush();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ use self::serde::de::Visitor;
|
|||
use self::serde::{de, Deserialize, Deserializer};
|
||||
extern crate unicode_segmentation;
|
||||
|
||||
|
||||
#[macro_use]
|
||||
mod position;
|
||||
#[macro_use]
|
||||
|
@ -35,3 +34,76 @@ pub use self::cells::*;
|
|||
pub use self::keys::*;
|
||||
pub use self::position::*;
|
||||
pub use self::text_editing::*;
|
||||
|
||||
use std::fmt;
|
||||
/*
|
||||
* CSI events we use
|
||||
*/
|
||||
|
||||
// Some macros taken from termion:
|
||||
/// Create a CSI-introduced sequence.
|
||||
macro_rules! csi {
|
||||
($( $l:expr ),*) => { concat!("\x1b[", $( $l ),*) };
|
||||
}
|
||||
|
||||
/// Derive a CSI sequence struct.
|
||||
macro_rules! derive_csi_sequence {
|
||||
($(#[$outer:meta])*
|
||||
($name:ident, $value:expr)) => {
|
||||
$(#[$outer])*
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct $name;
|
||||
|
||||
impl fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, csi!($value))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for $name {
|
||||
fn as_ref(&self) -> &'static [u8] {
|
||||
csi!($value).as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for $name {
|
||||
fn as_ref(&self) -> &'static str {
|
||||
csi!($value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
derive_csi_sequence!(
|
||||
#[doc = ""]
|
||||
(DisableMouse, "?1000l")
|
||||
);
|
||||
derive_csi_sequence!(
|
||||
#[doc = ""]
|
||||
(EnableMouse, "?1000h")
|
||||
);
|
||||
*/
|
||||
|
||||
derive_csi_sequence!(
|
||||
#[doc = "`CSI Ps ; Ps ; Ps t`, where `Ps = 2 2 ; 0` -> Save xterm icon and window title on stack."]
|
||||
(SaveWindowTitleIconToStack, "22;0t")
|
||||
);
|
||||
|
||||
derive_csi_sequence!(
|
||||
#[doc = "Restore window title and icon from terminal's title stack. `CSI Ps ; Ps ; Ps t`, where `Ps = 2 3 ; 0` -> Restore xterm icon and window title from stack."]
|
||||
(RestoreWindowTitleIconFromStack, "23;0t")
|
||||
);
|
||||
|
||||
derive_csi_sequence!(
|
||||
#[doc = "Empty struct with a Display implementation that returns the byte sequence to start [Bracketed Paste Mode](http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)"]
|
||||
(BracketModeStart, "?2004h")
|
||||
);
|
||||
|
||||
derive_csi_sequence!(
|
||||
#[doc = "Empty struct with a Display implementation that returns the byte sequence to end [Bracketed Paste Mode](http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)"]
|
||||
(BracketModeEnd, "?2003l")
|
||||
);
|
||||
|
||||
pub const BRACKET_PASTE_START: &[u8] = b"\x1B[200~";
|
||||
pub const BRACKET_PASTE_END: &[u8] = b"\x1B[201~";
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
use super::*;
|
||||
use crossbeam::{channel::Receiver, select};
|
||||
use serde::{Serialize, Serializer};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use termion::event::Event as TermionEvent;
|
||||
use termion::event::Key as TermionKey;
|
||||
|
@ -191,58 +190,6 @@ pub fn get_events(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CSI events we use
|
||||
*/
|
||||
|
||||
// Some macros taken from termion:
|
||||
/// Create a CSI-introduced sequence.
|
||||
macro_rules! csi {
|
||||
($( $l:expr ),*) => { concat!("\x1B[", $( $l ),*) };
|
||||
}
|
||||
|
||||
/// Derive a CSI sequence struct.
|
||||
macro_rules! derive_csi_sequence {
|
||||
($(#[$outer:meta])*
|
||||
($name:ident, $value:expr)) => {
|
||||
$(#[$outer])*
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct $name;
|
||||
|
||||
impl fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, csi!($value))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for $name {
|
||||
fn as_ref(&self) -> &'static [u8] {
|
||||
csi!($value).as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for $name {
|
||||
fn as_ref(&self) -> &'static str {
|
||||
csi!($value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
derive_csi_sequence!(
|
||||
#[doc = "Empty struct with a Display implementation that returns the byte sequence to start [Bracketed Paste Mode](http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)"]
|
||||
(BracketModeStart, "?2004h")
|
||||
);
|
||||
|
||||
derive_csi_sequence!(
|
||||
#[doc = "Empty struct with a Display implementation that returns the byte sequence to end [Bracketed Paste Mode](http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode)"]
|
||||
(BracketModeEnd, "?2003l")
|
||||
);
|
||||
|
||||
pub const BRACKET_PASTE_START: &[u8] = b"\x1B[200~";
|
||||
pub const BRACKET_PASTE_END: &[u8] = b"\x1B[201~";
|
||||
|
||||
const FIELDS: &[&str] = &[];
|
||||
|
||||
impl<'de> Deserialize<'de> for Key {
|
||||
|
|
Loading…
Reference in New Issue