Implementing SetTitle command (#429)

This commit is contained in:
Matheus Lessa Rodrigues 2020-05-16 05:41:43 +00:00 committed by GitHub
parent 43fbdfce0d
commit 88add302cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 4 deletions

View File

@ -18,6 +18,7 @@ pub enum ErrorKind {
Utf8Error(std::string::FromUtf8Error),
ParseIntError(std::num::ParseIntError),
ResizingTerminalFailure(String),
SettingTerminalTitleFailure,
#[doc(hidden)]
__Nonexhaustive,
}

View File

@ -62,6 +62,7 @@
//! [`ScrollDown`](terminal/struct.ScrollDown.html)
//! - Miscellaneous - [`Clear`](terminal/struct.Clear.html),
//! [`SetSize`](terminal/struct.SetSize.html)
//! [`SetTitle`](terminal/struct.SetTitle.html)
//! - Alternate screen - [`EnterAlternateScreen`](terminal/struct.EnterAlternateScreen.html),
//! [`LeaveAlternateScreen`](terminal/struct.LeaveAlternateScreen.html)
//!

View File

@ -7,7 +7,7 @@
// There are four macros in each group. For `Styler`, they are:
// * def_attr_base,
// * def_attr_generic,
// * impl_styler_callback,
// * impl_styler_callback,
// * impl_styler
//
// Fundamentally, any implementation works in a similar fashion; many methods with near-identical

View File

@ -302,6 +302,26 @@ impl Command for SetSize {
}
}
/// A command that sets the terminal title
///
/// # Notes
///
/// Commands must be executed/queued for execution otherwise they do nothing.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SetTitle<'a>(pub &'a str);
impl<'a> Command for SetTitle<'a> {
type AnsiType = String;
fn ansi_code(&self) -> Self::AnsiType {
ansi::set_title_ansi_sequence(self.0)
}
fn execute_winapi(&self) -> Result<()> {
sys::set_window_title(self.0)
}
}
impl_display!(for ScrollUp);
impl_display!(for ScrollDown);
impl_display!(for SetSize);

View File

@ -21,3 +21,7 @@ pub(crate) fn scroll_down_csi_sequence(count: u16) -> String {
pub(crate) fn set_size_csi_sequence(width: u16, height: u16) -> String {
format!(csi!("8;{};{}t"), height, width)
}
pub(crate) fn set_title_ansi_sequence(title: &str) -> String {
format!("\x1B]0;{}\x07", title)
}

View File

@ -4,7 +4,8 @@
pub(crate) use self::unix::{disable_raw_mode, enable_raw_mode, is_raw_mode_enabled, size};
#[cfg(windows)]
pub(crate) use self::windows::{
clear, disable_raw_mode, enable_raw_mode, scroll_down, scroll_up, set_size, size,
clear, disable_raw_mode, enable_raw_mode, scroll_down, scroll_up, set_size, set_window_title,
size,
};
#[cfg(windows)]

View File

@ -2,7 +2,7 @@
use crossterm_winapi::{Console, ConsoleMode, Coord, Handle, ScreenBuffer, Size};
use winapi::{
shared::minwindef::DWORD,
um::wincon::{ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT},
um::wincon::{SetConsoleTitleW, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT},
};
use crate::{cursor, terminal::ClearType, ErrorKind, Result};
@ -190,6 +190,17 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
Ok(())
}
pub(crate) fn set_window_title(title: &str) -> Result<()> {
let mut title: Vec<_> = title.encode_utf16().collect();
title.push(0);
let result = unsafe { SetConsoleTitleW(title.as_ptr()) };
if result != 0 {
Ok(())
} else {
Err(ErrorKind::SettingTerminalTitleFailure)
}
}
fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> {
let (mut x, mut y) = (location.x, location.y);
@ -282,9 +293,13 @@ fn clear_winapi(start_location: Coord, cells_to_write: u32, current_attribute: u
#[cfg(test)]
mod tests {
use std::{ffi::OsString, os::windows::ffi::OsStringExt};
use winapi::um::wincon::GetConsoleTitleW;
use crossterm_winapi::ScreenBuffer;
use super::{scroll_down, scroll_up, set_size, size};
use super::{scroll_down, scroll_up, set_size, set_window_title, size};
#[test]
fn test_resize_winapi() {
@ -344,4 +359,17 @@ mod tests {
assert_eq!(new_window.top, current_window.top - 2);
assert_eq!(new_window.bottom, current_window.bottom - 2);
}
#[test]
fn test_set_title_winapi() {
let test_title = "this is a crossterm test title";
set_window_title(test_title).unwrap();
let mut raw = [0 as u16; 128];
let length = unsafe { GetConsoleTitleW(raw.as_mut_ptr(), raw.len() as u32) } as usize;
assert_ne!(0, length);
let console_title = OsString::from_wide(&raw[..length]).into_string().unwrap();
assert_eq!(test_title, &console_title[..]);
}
}