[Terminal] Adding a terminal to Cadmus - #77
Conversation
a73a4da to
d84fb3c
Compare
|
@OGKevin I cleaned up the diff, let me know what you think. |
OGKevin
left a comment
There was a problem hiding this comment.
Thanks for the PR and kudos!
I did an initial pass, I have some feedback:
- I would appriciate if you can add some rust docs, especially a high level one on the module, and for most/all of the public API. Also sone of the internals that you deem worthy. Feel free to use an LLM for it, just make sure its not too sloppy and accurate.
- I am of the opinion, that if you need inline comment, that logic should be extracted into a dedicated documented function, could you apply this principle please. (I'll make sure to create contributing instructions as well)
On the keyboard, when you press shift, there is a clear indicator that your next press is going to be a of the shift layer. With the introduction of the control key, this is not the same. When you press control, there is no indicator that the next key will be with pressed with the control modifier.
Would it make sense to add an indicator?
If you could rebase on top of 2935916, I can enable the CI. I believe cargo clippy might have some feedback :D
| Event::WakeUp => { | ||
| if let Ok(mut buffer) = self.double_buffer.lock() { | ||
| if buffer.is_dirty() { | ||
| if buffer.take_full_refresh() { | ||
| rq.add(RenderData::no_wait(self.id, self.rect, UpdateMode::Gui)); | ||
| } else { | ||
| for dirty_rect in buffer.drain_dirty_rects() { | ||
| let update_rect = Rectangle::new( | ||
| Point::new(self.rect.min.x + dirty_rect.min.x, self.rect.min.y + dirty_rect.min.y), | ||
| Point::new(self.rect.min.x + dirty_rect.max.x, self.rect.min.y + dirty_rect.max.y), | ||
| ); | ||
| rq.add(RenderData::no_wait(self.id, update_rect, UpdateMode::FastMono)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| true | ||
| } |
There was a problem hiding this comment.
What is the reason for capturing this event and not let it continue up the chain?
| let saved_layout = context.settings.keyboard_layout.clone(); | ||
| context.settings.keyboard_layout = "Terminal".to_string(); | ||
|
|
||
| let mut kb_rect = rect![ | ||
| rect.min.x, | ||
| rect.max.y - (small_height + 3 * big_height) as i32 + big_thickness, | ||
| rect.max.x, | ||
| rect.max.y | ||
| ]; | ||
| let keyboard = Keyboard::new(&mut kb_rect, false, context); | ||
| children.push(Box::new(keyboard) as Box<dyn View>); | ||
|
|
||
| context.settings.keyboard_layout = saved_layout; | ||
|
|
There was a problem hiding this comment.
This feels a bit dirty haha. But I guess this is needed due to no way of telling the keyboard which layout to render directly.
I suggest extracting this into a function with #[inline] so it can be documented.
| let (_, big_thickness) = halves(thickness); | ||
|
|
||
| let saved_layout = context.settings.keyboard_layout.clone(); | ||
| context.settings.keyboard_layout = "Terminal".to_string(); |
There was a problem hiding this comment.
Could you introduce an enum for this please 🙏
| let emulator_shared = Arc::new(Mutex::new(Emulator::new(rows, cols))); | ||
| let shutdown_flag = Arc::new(AtomicBool::new(false)); | ||
|
|
||
| let hub = hub.clone(); | ||
| let buffer_shared = Arc::clone(&double_buffer); | ||
| let emulator_shared = Arc::clone(&emulator_shared); |
There was a problem hiding this comment.
Am I missing something 👀
Whats the reason for 2x emulator_shared?
| Err(e) => { | ||
| eprintln!("Failed to create terminal: {}", e); | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Since this is the emulator, lets just panic 💣
| EntryId::Launch(AppCmd::Calculator), | ||
| ), | ||
| EntryKind::Command("Sketch".to_string(), EntryId::Launch(AppCmd::Sketch)), | ||
| EntryKind::Command("Terminal".to_string(), EntryId::Launch(AppCmd::Terminal)), |
There was a problem hiding this comment.
Can you introduce an enum here as well.
The terminal command can be the first and only entry. And you can use to_string() on it.
Add a todo comment so that later on it can be refactored.
So that EntryKind::Command takes the enum instead of strings.
There was a problem hiding this comment.
I have a feeling this suggestion should be a separate issue. Maybe I am misunderstanding the ask but my instinct is that I want to keep this diff as specific to the terminal application as possible.
| let dpi = CURRENT_DEVICE.dpi; | ||
| let font_size_scaled = (font_size * 64.0) as u32; | ||
|
|
||
| // Setup menu icon in top right corner |
There was a problem hiding this comment.
I would appriciate if you extract this into a dedicated function using #[inline] and document that function if needed.
| .corners(Some(CornerSpec::Uniform(border_radius))); | ||
| children.push(Box::new(icon) as Box<dyn View>); | ||
|
|
||
| // Add terminal keyboard |
There was a problem hiding this comment.
Same ask here and all the ones that follow.
I believe it becomes easier to follow to break this big function down into smaller ones with #[inline].
|
|
||
| const ICON_NAME: &str = "enclosed_menu"; | ||
|
|
||
| pub struct Terminal { |
There was a problem hiding this comment.
Can you add some rust docs explaning the public API.
I am also fine if you decide to use an LLM for it, just make sure its not too sloppy.
As I read the code I need to go throught the thinking process that you might have already done.
So it would be nicer to document it, instead of having everyone do the same thinking process!
| @@ -0,0 +1,7 @@ | |||
| mod buffer; | |||
There was a problem hiding this comment.
Can you add a high level rustdoc for the entire module 🙏
feat: add terminal font size setting and update terminal initialization fix: correct key mapping for Tab in terminal layout fix: dirty rectangle management in DoubleBuffer and session, this should eliminate the issue with characters being left behind on the screen when many frames are pushed in a short period of time.
THIS IS A WORK IN PROGRESS BUT IM PUTTING IT HERE INCASE PEOPLE WANNA TRY IT
I was working off of the head of Plato so there are a few extra commits from the HEAD of Plato, not sure if you are planning on syncing upstream changes
This pull request introduces a new terminal emulator feature, including all the necessary backend, UI, and keyboard integration. It also adds support for more keyboard keys and events. The most significant changes are the addition of the terminal view and its supporting modules, enhancements to keyboard handling (including new key kinds and events), and the integration of external crates to support terminal emulation and PTY functionality.
Terminal Emulator Integration
terminalmodule with submodules for buffer management, VT100 emulation, PTY handling, rendering, and session management. The main entry point isTerminalinsession.rs. (crates/core/src/view/terminal/buffer.rs[1]crates/core/src/view/terminal/emulator.rs[2]crates/core/src/view/terminal/pty.rs[3]crates/core/src/view/terminal/mod.rs[4])AppCmd::Terminal) and view (ViewId::Terminal), and added it to the main menu. (crates/core/src/view/mod.rs[1] [2]crates/core/src/view/common.rs[3])Keyboard and Input Handling Enhancements
KeyKindvariants for Tab, Escape, Control, and Arrow keys, including deserialization and display logic. (crates/core/src/view/key.rs[1] [2] [3] [4])crates/core/src/view/keyboard.rs[1] [2] [3] [4] [5])KeyboardEventwithRawandControlvariants to allow sending raw byte sequences and control characters. (crates/core/src/view/mod.rs)crates/core/src/view/input_field.rs[1]crates/core/src/view/key.rs[2])Dependency and Version Updates
vt100(via a patched branch for extra features) andportable-ptyas dependencies to support terminal emulation and PTY spawning. (Cargo.toml[1]crates/core/Cargo.toml[2])