pub struct SurfaceOptions {
pub id: Option<String>,
pub mode: Mode,
pub title: Option<String>,
pub role: Option<String>,
pub listen: bool,
pub adopt: bool,
pub keep: bool,
}Expand description
How to open a surface.
Fields§
§id: Option<String>The id (default s1, s2, … per session).
mode: ModeThe mode.
title: Option<String>Names the pane until the program sets its own title.
role: Option<String>data-surface for stylesheets.
listen: boolWhether the program reads its events (default true).
adopt: boolReopen a closed inline surface with this id.
keep: boolKeep it on screen when the session closes it (default true).
Implementations§
Source§impl SurfaceOptions
impl SurfaceOptions
Sourcepub fn inline() -> Self
pub fn inline() -> Self
An inline surface (a session program).
Examples found in repository?
examples/chat.rs (line 132)
127fn main() -> Result<(), tern_sdk::Error> {
128 let Some(mut session) = Session::connect(Options::new().feature(feature::SEND))? else {
129 println!("chat needs a terminal that speaks TSP (Tern).");
130 return Ok(());
131 };
132 let sf = session.open(SurfaceOptions::inline().title("chat"))?;
133 let mut chat = Chat::default();
134 session.render(sf, chat.view())?;
135 session.focus(sf, Some(EDITOR))?;
136 while let Some(input) = session.next(None)? {
137 match input {
138 Input::Key(key) => {
139 if key.is("escape") || key.is("ctrl+c") || key.is("ctrl+d") {
140 break;
141 }
142 match key.name.as_str() {
143 "enter" if !key.shift && !key.alt => {
144 let text = std::mem::take(&mut chat.draft);
145 chat.cursor = 0;
146 chat.send(text);
147 },
148 "enter" => chat.insert("\n"),
149 "backspace" if chat.cursor > 0 => {
150 let at = chat.byte(chat.cursor - 1);
151 chat.draft.remove(at);
152 chat.cursor -= 1;
153 },
154 "delete" if chat.cursor < chat.draft.chars().count() => {
155 let at = chat.byte(chat.cursor);
156 chat.draft.remove(at);
157 },
158 "left" => chat.cursor = chat.cursor.saturating_sub(1),
159 "right" => chat.cursor = (chat.cursor + 1).min(chat.draft.chars().count()),
160 "home" => chat.cursor = 0,
161 "end" => chat.cursor = chat.draft.chars().count(),
162 "paste" => chat.insert(key.text.as_deref().unwrap_or_default()),
163 _ => match key.typed() {
164 Some(text) => chat.insert(text),
165 None => continue,
166 },
167 }
168 },
169 Input::Msg(Msg::Send(text), _) => chat.send(text),
170 Input::Msg(Msg::Focus, _) => session.focus(sf, Some(EDITOR))?,
171 Input::Event(_) => continue,
172 }
173 session.render(sf, chat.view())?;
174 }
175 session.close()?;
176 println!("Chat closed after {} messages.", chat.transcript.len());
177 Ok(())
178}Sourcepub fn flow() -> Self
pub fn flow() -> Self
A flow surface (command output that stays in the scrollback).
Examples found in repository?
examples/progress.rs (line 111)
101fn main() -> Result<(), tern_sdk::Error> {
102 let Some(mut session) = Session::connect(Options::new())? else {
103 for (i, step) in STEPS.iter().enumerate() {
104 println!("[{}/{}] {step}", i + 1, STEPS.len());
105 std::thread::sleep(STEP);
106 }
107 println!("Built demo.");
108 return Ok(());
109 };
110 let start = Instant::now();
111 let sf = session.open(SurfaceOptions::flow().title("progress"))?;
112 let mut build =
113 Build { log: String::new(), done: 0, took: None, status: Status::Running };
114 session.render(sf, view(&build))?;
115 for step in STEPS {
116 if wait(&mut session, STEP)? {
117 build.status = Status::Cancelled;
118 break;
119 }
120 build.log.push_str("\x1b[32m✓\x1b[0m ");
121 build.log.push_str(step);
122 build.log.push_str("\r\n");
123 build.done += 1;
124 session.render(sf, view(&build))?;
125 }
126 if build.status == Status::Running {
127 build.status = Status::Done;
128 }
129 let took = start.elapsed();
130 build.took = Some(took.as_millis() as u64);
131 session.render(sf, view(&build))?;
132 session.close()?;
133 match build.status {
134 Status::Done => println!("Built demo in {:.1}s.", took.as_secs_f64()),
135 _ => println!("Build cancelled."),
136 }
137 Ok(())
138}Sourcepub fn title(self, title: impl Into<String>) -> Self
pub fn title(self, title: impl Into<String>) -> Self
Sets the title.
Examples found in repository?
examples/progress.rs (line 111)
101fn main() -> Result<(), tern_sdk::Error> {
102 let Some(mut session) = Session::connect(Options::new())? else {
103 for (i, step) in STEPS.iter().enumerate() {
104 println!("[{}/{}] {step}", i + 1, STEPS.len());
105 std::thread::sleep(STEP);
106 }
107 println!("Built demo.");
108 return Ok(());
109 };
110 let start = Instant::now();
111 let sf = session.open(SurfaceOptions::flow().title("progress"))?;
112 let mut build =
113 Build { log: String::new(), done: 0, took: None, status: Status::Running };
114 session.render(sf, view(&build))?;
115 for step in STEPS {
116 if wait(&mut session, STEP)? {
117 build.status = Status::Cancelled;
118 break;
119 }
120 build.log.push_str("\x1b[32m✓\x1b[0m ");
121 build.log.push_str(step);
122 build.log.push_str("\r\n");
123 build.done += 1;
124 session.render(sf, view(&build))?;
125 }
126 if build.status == Status::Running {
127 build.status = Status::Done;
128 }
129 let took = start.elapsed();
130 build.took = Some(took.as_millis() as u64);
131 session.render(sf, view(&build))?;
132 session.close()?;
133 match build.status {
134 Status::Done => println!("Built demo in {:.1}s.", took.as_secs_f64()),
135 _ => println!("Build cancelled."),
136 }
137 Ok(())
138}More examples
examples/chat.rs (line 132)
127fn main() -> Result<(), tern_sdk::Error> {
128 let Some(mut session) = Session::connect(Options::new().feature(feature::SEND))? else {
129 println!("chat needs a terminal that speaks TSP (Tern).");
130 return Ok(());
131 };
132 let sf = session.open(SurfaceOptions::inline().title("chat"))?;
133 let mut chat = Chat::default();
134 session.render(sf, chat.view())?;
135 session.focus(sf, Some(EDITOR))?;
136 while let Some(input) = session.next(None)? {
137 match input {
138 Input::Key(key) => {
139 if key.is("escape") || key.is("ctrl+c") || key.is("ctrl+d") {
140 break;
141 }
142 match key.name.as_str() {
143 "enter" if !key.shift && !key.alt => {
144 let text = std::mem::take(&mut chat.draft);
145 chat.cursor = 0;
146 chat.send(text);
147 },
148 "enter" => chat.insert("\n"),
149 "backspace" if chat.cursor > 0 => {
150 let at = chat.byte(chat.cursor - 1);
151 chat.draft.remove(at);
152 chat.cursor -= 1;
153 },
154 "delete" if chat.cursor < chat.draft.chars().count() => {
155 let at = chat.byte(chat.cursor);
156 chat.draft.remove(at);
157 },
158 "left" => chat.cursor = chat.cursor.saturating_sub(1),
159 "right" => chat.cursor = (chat.cursor + 1).min(chat.draft.chars().count()),
160 "home" => chat.cursor = 0,
161 "end" => chat.cursor = chat.draft.chars().count(),
162 "paste" => chat.insert(key.text.as_deref().unwrap_or_default()),
163 _ => match key.typed() {
164 Some(text) => chat.insert(text),
165 None => continue,
166 },
167 }
168 },
169 Input::Msg(Msg::Send(text), _) => chat.send(text),
170 Input::Msg(Msg::Focus, _) => session.focus(sf, Some(EDITOR))?,
171 Input::Event(_) => continue,
172 }
173 session.render(sf, chat.view())?;
174 }
175 session.close()?;
176 println!("Chat closed after {} messages.", chat.transcript.len());
177 Ok(())
178}Trait Implementations§
Source§impl Clone for SurfaceOptions
impl Clone for SurfaceOptions
Source§impl Debug for SurfaceOptions
impl Debug for SurfaceOptions
Auto Trait Implementations§
impl Freeze for SurfaceOptions
impl RefUnwindSafe for SurfaceOptions
impl Send for SurfaceOptions
impl Sync for SurfaceOptions
impl Unpin for SurfaceOptions
impl UnsafeUnpin for SurfaceOptions
impl UnwindSafe for SurfaceOptions
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more