Added cursor blink and settings

This commit is contained in:
Mikayla Maki 2022-08-15 18:05:07 -07:00
parent 7b3a7727c6
commit bba51c3ae6
6 changed files with 104 additions and 26 deletions

View file

@ -102,6 +102,19 @@
// //
// //
"working_directory": "current_project_directory", "working_directory": "current_project_directory",
//Set the cursor blinking behavior in the terminal.
//May take 4 values:
// 1. Never blink the cursor, ignoring the terminal mode
// "blinking": "never",
// 2. Default the cursor blink to off, but allow the terminal to
// turn blinking on
// "blinking": "off",
// 3. Default the cursor blink to on, but allow the terminal to
// turn blinking off
// "blinking": "on",
// 4. Always blink the cursor, ignoring the terminal mode
// "blinking": "always",
"blinking": "on",
//Any key-value pairs added to this list will be added to the terminal's //Any key-value pairs added to this list will be added to the terminal's
//enviroment. Use `:` to seperate multiple values. //enviroment. Use `:` to seperate multiple values.
"env": { "env": {

View file

@ -83,6 +83,22 @@ pub struct TerminalSettings {
pub font_size: Option<f32>, pub font_size: Option<f32>,
pub font_family: Option<String>, pub font_family: Option<String>,
pub env: Option<HashMap<String, String>>, pub env: Option<HashMap<String, String>>,
pub blinking: Option<TerminalBlink>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum TerminalBlink {
Never,
On,
Off,
Always,
}
impl Default for TerminalBlink {
fn default() -> Self {
TerminalBlink::On
}
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, JsonSchema)]

View file

@ -21,7 +21,7 @@ use gpui::{
}; };
use itertools::Itertools; use itertools::Itertools;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use settings::Settings; use settings::{Settings, TerminalBlink};
use theme::TerminalStyle; use theme::TerminalStyle;
use util::ResultExt; use util::ResultExt;
@ -201,6 +201,7 @@ pub struct TerminalEl {
view: WeakViewHandle<ConnectedView>, view: WeakViewHandle<ConnectedView>,
modal: bool, modal: bool,
focused: bool, focused: bool,
blink_state: bool,
} }
impl TerminalEl { impl TerminalEl {
@ -209,12 +210,14 @@ impl TerminalEl {
terminal: WeakModelHandle<Terminal>, terminal: WeakModelHandle<Terminal>,
modal: bool, modal: bool,
focused: bool, focused: bool,
blink_state: bool,
) -> TerminalEl { ) -> TerminalEl {
TerminalEl { TerminalEl {
view, view,
terminal, terminal,
modal, modal,
focused, focused,
blink_state,
} }
} }
@ -568,6 +571,33 @@ impl TerminalEl {
(point, side) (point, side)
} }
pub fn should_show_cursor(
settings: Option<TerminalBlink>,
blinking_on: bool,
focused: bool,
blink_show: bool,
) -> bool {
if !focused {
true
} else {
match settings {
Some(setting) => match setting {
TerminalBlink::Never => true,
TerminalBlink::On | TerminalBlink::Off if blinking_on => blink_show,
TerminalBlink::On | TerminalBlink::Off /*if !blinking_on */ => true,
TerminalBlink::Always => focused && blink_show,
},
None => {
if blinking_on {
blink_show
} else {
false
}
}
}
}
}
} }
impl Element for TerminalEl { impl Element for TerminalEl {
@ -580,6 +610,7 @@ impl Element for TerminalEl {
cx: &mut gpui::LayoutContext, cx: &mut gpui::LayoutContext,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let blink_settings = settings.terminal_overrides.blinking.clone();
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();
//Setup layout information //Setup layout information
@ -598,13 +629,13 @@ impl Element for TerminalEl {
terminal_theme.colors.background terminal_theme.colors.background
}; };
let (cells, selection, cursor, display_offset, cursor_text) = self let (cells, selection, cursor, display_offset, cursor_text, blink_mode) = self
.terminal .terminal
.upgrade(cx) .upgrade(cx)
.unwrap() .unwrap()
.update(cx.app, |terminal, mcx| { .update(cx.app, |terminal, mcx| {
terminal.set_size(dimensions); terminal.set_size(dimensions);
terminal.render_lock(mcx, |content, cursor_text| { terminal.render_lock(mcx, |content, cursor_text, style| {
let mut cells = vec![]; let mut cells = vec![];
cells.extend( cells.extend(
content content
@ -628,6 +659,7 @@ impl Element for TerminalEl {
content.cursor, content.cursor,
content.display_offset, content.display_offset,
cursor_text, cursor_text,
style,
) )
}) })
}); });
@ -643,19 +675,13 @@ impl Element for TerminalEl {
); );
//Layout cursor //Layout cursor
//TODO: This logic can be a lot better
let show_cursor = if let Some(view_handle) = self.view.upgrade(cx) {
if view_handle.read(cx).show_cursor() {
false
} else {
true
}
} else {
true
};
let cursor = { let cursor = {
if show_cursor { if !TerminalEl::should_show_cursor(
blink_settings,
blink_mode,
self.focused,
self.blink_state,
) {
None None
} else { } else {
let cursor_point = DisplayCursor::from(cursor.point, display_offset); let cursor_point = DisplayCursor::from(cursor.point, display_offset);

View file

@ -132,7 +132,7 @@ impl ConnectedView {
} }
//Following code copied from editor cursor //Following code copied from editor cursor
pub fn show_cursor(&self) -> bool { pub fn blink_show(&self) -> bool {
self.blinking_paused || self.show_cursor self.blinking_paused || self.show_cursor
} }
@ -253,9 +253,15 @@ impl View for ConnectedView {
Stack::new() Stack::new()
.with_child( .with_child(
TerminalEl::new(cx.handle(), terminal_handle, self.modal, focused) TerminalEl::new(
.contained() cx.handle(),
.boxed(), terminal_handle,
self.modal,
focused,
self.blink_show(),
)
.contained()
.boxed(),
) )
.with_child(ChildView::new(&self.context_menu).boxed()) .with_child(ChildView::new(&self.context_menu).boxed())
.boxed() .boxed()

View file

@ -25,7 +25,7 @@ use futures::{
}; };
use modal::deploy_modal; use modal::deploy_modal;
use settings::{Settings, Shell}; use settings::{Settings, Shell, TerminalBlink};
use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration}; use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration};
use thiserror::Error; use thiserror::Error;
@ -254,6 +254,7 @@ impl TerminalBuilder {
shell: Option<Shell>, shell: Option<Shell>,
env: Option<HashMap<String, String>>, env: Option<HashMap<String, String>>,
initial_size: TerminalSize, initial_size: TerminalSize,
blink_settings: Option<TerminalBlink>,
) -> Result<TerminalBuilder> { ) -> Result<TerminalBuilder> {
let pty_config = { let pty_config = {
let alac_shell = shell.clone().and_then(|shell| match shell { let alac_shell = shell.clone().and_then(|shell| match shell {
@ -290,7 +291,18 @@ impl TerminalBuilder {
//TODO: Remove with a bounded sender which can be dispatched on &self //TODO: Remove with a bounded sender which can be dispatched on &self
let (events_tx, events_rx) = unbounded(); let (events_tx, events_rx) = unbounded();
//Set up the terminal... //Set up the terminal...
let term = Term::new(&config, &initial_size, ZedListener(events_tx.clone())); let mut term = Term::new(&config, &initial_size, ZedListener(events_tx.clone()));
//Start off blinking if we need to
match blink_settings {
Some(setting) => match setting {
TerminalBlink::On | TerminalBlink::Always => {
term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor)
}
_ => {}
},
None => term.set_mode(alacritty_terminal::ansi::Mode::BlinkingCursor),
}
let term = Arc::new(FairMutex::new(term)); let term = Arc::new(FairMutex::new(term));
//Setup the pty... //Setup the pty...
@ -322,7 +334,7 @@ impl TerminalBuilder {
//And connect them together //And connect them together
let event_loop = EventLoop::new( let event_loop = EventLoop::new(
term.clone(), term.clone(),
ZedListener(events_tx), ZedListener(events_tx.clone()),
pty, pty,
pty_config.hold, pty_config.hold,
false, false,
@ -583,7 +595,7 @@ impl Terminal {
pub fn render_lock<F, T>(&mut self, cx: &mut ModelContext<Self>, f: F) -> T pub fn render_lock<F, T>(&mut self, cx: &mut ModelContext<Self>, f: F) -> T
where where
F: FnOnce(RenderableContent, char) -> T, F: FnOnce(RenderableContent, char, bool) -> T,
{ {
let m = self.term.clone(); //Arc clone let m = self.term.clone(); //Arc clone
let mut term = m.lock(); let mut term = m.lock();
@ -599,7 +611,7 @@ impl Terminal {
let cursor_text = term.grid()[content.cursor.point].c; let cursor_text = term.grid()[content.cursor.point].c;
f(content, cursor_text) f(content, cursor_text, term.cursor_style().blinking)
} }
///Scroll the terminal ///Scroll the terminal

View file

@ -94,8 +94,13 @@ impl TerminalView {
let shell = settings.terminal_overrides.shell.clone(); let shell = settings.terminal_overrides.shell.clone();
let envs = settings.terminal_overrides.env.clone(); //Should be short and cheap. let envs = settings.terminal_overrides.env.clone(); //Should be short and cheap.
let content = match TerminalBuilder::new(working_directory.clone(), shell, envs, size_info) let content = match TerminalBuilder::new(
{ working_directory.clone(),
shell,
envs,
size_info,
settings.terminal_overrides.blinking.clone(),
) {
Ok(terminal) => { Ok(terminal) => {
let terminal = cx.add_model(|cx| terminal.subscribe(cx)); let terminal = cx.add_model(|cx| terminal.subscribe(cx));
let view = cx.add_view(|cx| ConnectedView::from_terminal(terminal, modal, cx)); let view = cx.add_view(|cx| ConnectedView::from_terminal(terminal, modal, cx));