pub struct Key {
pub name: String,
pub text: Option<String>,
pub ctrl: bool,
pub alt: bool,
pub shift: bool,
pub meta: bool,
}Expand description
One key press, or a paste (name "paste" with its text).
Fields§
§name: StringThe key: a lowercase character ("a", "é"), "space", a named key
("enter", "up", "f5", …) or "paste".
text: Option<String>What the key types, when it types something.
ctrl: boolControl held.
alt: boolAlt (Option) held.
shift: boolShift held.
meta: boolCmd on macOS, Super elsewhere.
Implementations§
Source§impl Key
impl Key
Sourcepub fn is(&self, chord: &str) -> bool
pub fn is(&self, chord: &str) -> bool
Whether this is the chord chord: modifiers and a name joined by +
("ctrl+c", "shift+tab", "escape", "ctrl++"), every modifier
matching exactly.
§Example
use tern_sdk::keys::Key;
let key = Key { ctrl: true, ..Key::named("c") };
assert!(key.is("ctrl+c"));
assert!(!key.is("c"));Examples found in repository?
More examples
examples/chat.rs (line 139)
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 typed(&self) -> Option<&str>
pub fn typed(&self) -> Option<&str>
Whether the key types text without Control, Alt or Meta held.
Examples found in repository?
examples/chat.rs (line 163)
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§
impl Eq for Key
impl StructuralPartialEq for Key
Auto Trait Implementations§
impl Freeze for Key
impl RefUnwindSafe for Key
impl Send for Key
impl Sync for Key
impl Unpin for Key
impl UnsafeUnpin for Key
impl UnwindSafe for Key
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