aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2017-01-10 21:21:19 -0800
committerJoe Wilm <jwilm@users.noreply.github.com>2017-01-11 09:07:31 -0800
commitdfb1b3bb5c5e9d9d9ee23f3f5bcc84fe6602392d (patch)
treefd1cbff66bbc40993ddcb89a6b62e53f06652e79 /src
parent4fb7801ba3515922e3dbb8b27c1c28ec2efaf22b (diff)
downloadalacritty-dfb1b3bb5c5e9d9d9ee23f3f5bcc84fe6602392d.tar.gz
alacritty-dfb1b3bb5c5e9d9d9ee23f3f5bcc84fe6602392d.zip
Add support for setting title from OSC
Resolves #23 Resolves #144
Diffstat (limited to 'src')
-rw-r--r--src/ansi.rs62
-rw-r--r--src/display.rs4
-rw-r--r--src/macros.rs10
-rw-r--r--src/term/mod.rs17
-rw-r--r--src/window.rs6
5 files changed, 83 insertions, 16 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index 4c7ce5b7..b8b063f4 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -13,8 +13,9 @@
// limitations under the License.
//
//! ANSI Terminal Stream Parsing
-use std::ops::Range;
use std::io;
+use std::ops::Range;
+use std::str;
use vte;
@@ -98,6 +99,9 @@ pub trait TermInfo {
/// XXX Should probably not provide default impls for everything, but it makes
/// writing specific handler impls for tests far easier.
pub trait Handler {
+ /// OSC to set window title
+ fn set_title(&mut self, &str) {}
+
/// A character to be displayed
fn input(&mut self, _c: char) {}
@@ -455,9 +459,9 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W>
}
#[inline]
- fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, byte: u8) {
- err_println!("[unhandled hook] params={:?}, ints: {:?}, ignore: {:?}, byte={:?}",
- params, intermediates, ignore, byte as char);
+ fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool) {
+ err_println!("[unhandled hook] params={:?}, ints: {:?}, ignore: {:?}",
+ params, intermediates, ignore);
}
#[inline]
@@ -466,23 +470,49 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W>
}
#[inline]
- fn unhook(&mut self, byte: u8) {
- err_println!("[unhandled unhook] byte={:?}", byte);
+ fn unhook(&mut self) {
+ err_println!("[unhandled unhook]");
}
#[inline]
- fn osc_start(&mut self) {
- err_println!("[unhandled osc_start]");
- }
+ fn osc_dispatch(&mut self, params: &[&[u8]]) {
+ macro_rules! unhandled {
+ () => {{
+ err_print!("[unhandled osc_dispatch]: [");
+ for param in params {
+ err_print!("[");
+ for byte in *param {
+ err_print!("{:?}, ", *byte as char);
+ }
+ err_print!("],");
+ }
+ err_println!("]");
+ }}
+ }
- #[inline]
- fn osc_put(&mut self, byte: u8) {
- err_println!("[unhandled osc_put] byte={:?}", byte as char);
- }
+ if params.len() != 2 {
+ unhandled!();
+ return;
+ }
- #[inline]
- fn osc_end(&mut self, byte: u8) {
- err_println!("[unhandled osc_end] byte={:?}", byte);
+ let kind = params[0];
+ let arg = params[1];
+
+ if kind.is_empty() || arg.is_empty() {
+ unhandled!();
+ return;
+ }
+
+ match kind[0] {
+ b'0' | b'2' => {
+ if let Ok(utf8_title) = str::from_utf8(arg) {
+ self.handler.set_title(utf8_title);
+ }
+ },
+ _ => {
+ unhandled!();
+ }
+ }
}
#[inline]
diff --git a/src/display.rs b/src/display.rs
index dccbd7fe..5aa3bac4 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -272,6 +272,10 @@ impl Display {
// Clear dirty flag
terminal.dirty = false;
+ if let Some(title) = terminal.get_next_title() {
+ self.window.set_title(&title);
+ }
+
{
let glyph_cache = &mut self.glyph_cache;
// Draw grid
diff --git a/src/macros.rs b/src/macros.rs
index a6e30104..c96e6d64 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -31,6 +31,16 @@ macro_rules! err_println {
}
#[macro_export]
+macro_rules! err_print {
+ ($($arg:tt)*) => {{
+ if cfg!(feature = "err-println") {
+ use std::io::Write;
+ (write!(&mut ::std::io::stderr(), $($arg)*)).expect("stderr");
+ }
+ }}
+}
+
+#[macro_export]
macro_rules! debug_println {
($($t:tt)*) => {
if cfg!(debug_assertions) {
diff --git a/src/term/mod.rs b/src/term/mod.rs
index cc1715a9..581f5039 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -210,6 +210,11 @@ pub struct Term {
/// arrays. Without it we wold have to sanitize cursor.col every time we used it.
input_needs_wrap: bool,
+ /// Got a request to set title; it's buffered here until next draw.
+ ///
+ /// Would be nice to avoid the allocation...
+ next_title: Option<String>,
+
/// Alternate grid
alt_grid: Grid<Cell>,
@@ -286,6 +291,11 @@ impl SizeInfo {
}
impl Term {
+ #[inline]
+ pub fn get_next_title(&mut self) -> Option<String> {
+ self.next_title.take()
+ }
+
pub fn new(size: SizeInfo) -> Term {
let template = Cell::default();
@@ -304,6 +314,7 @@ impl Term {
let scroll_region = Line(0)..grid.num_lines();
Term {
+ next_title: None,
dirty: false,
input_needs_wrap: false,
grid: grid,
@@ -642,6 +653,12 @@ impl ansi::TermInfo for Term {
}
impl ansi::Handler for Term {
+ /// Set the window title
+ #[inline]
+ fn set_title(&mut self, title: &str) {
+ self.next_title = Some(title.to_owned());
+ }
+
/// A character to be displayed
#[inline]
fn input(&mut self, c: char) {
diff --git a/src/window.rs b/src/window.rs
index 40729e99..a5f6e2c6 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -282,6 +282,12 @@ impl Window {
pub fn wait_events(&self) -> glutin::WaitEventsIterator {
self.glutin_window.wait_events()
}
+
+ /// Set the window title
+ #[inline]
+ pub fn set_title(&self, title: &str) {
+ self.glutin_window.set_title(title);
+ }
}
impl Proxy {