0

I'm currently learning Rust and I have been struggling for some time with closures. What I'm trying to do is to create an instance of Terminal, pass it inside a closure and then return that Terminal instance.

Here's the code:

/// Initialize the screen
fn init_screen() -> Terminal {
    let mut terminal = Terminal::init();

    terminal.enable_raw_mode();
    terminal.enter_alternate_screen();
    terminal.clear();
    terminal.move_cursor(0, 0);
    terminal.hide_cursor();
    terminal.enable_mouse();

    terminal.event_handler.register_key(
        KeyCode::Esc,
        Box::new(|_| {
            terminal.clear();
        })
    );

    terminal
}

Now this is something that would work without problems had it been TypeScript for example but I'm having problems implementing this in Rust because of the ownership and mutability rules.

How would this pattern be implemented in Rust?

Edit:

The error I receive from the compiler is this:

error[E0499]: cannot borrow `terminal.event_handler` as mutable more than once at a time
  --> /home/silvio/Programming/Projects/rustier/src/lib.rs:30:5
   |
30 |  /     terminal.event_handler.register_key(
31 |  |         KeyCode::Esc,
32 |  |         Box::new(|_| {
   |  |         -        --- first mutable borrow occurs here
   |  |_________|
   | ||
33 | ||             // let ref_terminal = *terminal.borrow_mut();
34 | ||             terminal.clear();
   | ||             -------- first borrow occurs due to use of `terminal` in closure
35 | ||             // ref_terminal.disable_mouse();
...  ||
40 | ||             std::process::exit(0);
41 | ||         })
   | ||__________- cast requires that `terminal` is borrowed for `'static`
42 |  |     );
   |  |_____^ second mutable borrow occurs here
siannone
  • 6,617
  • 15
  • 59
  • 89
  • I would not call `std::process::exit` there anyway. This would prevent all kinds of cleanup (you manually clear the terminal here, but as your application grows, there might be other things to cleanup). – mcarton May 15 '20 at 12:17
  • Do you have some kind of event loop? – mcarton May 15 '20 at 12:17
  • @mcarton I have updated the question with error I receive from the compiler. Regarding the event loop question: I'm trying to implement one. BTW the question you linked is not related to my problem. – siannone May 15 '20 at 12:21
  • The duplicate question is related: You are trying to store a reference to `terminal` in a lambda that you store in `terminal.event_handler`. – mcarton May 15 '20 at 12:37
  • Since you will have an event loop, a better way to solve your problem would be to pass a object to `init_screen` that can cancel the event loop (the exact type of the object depends on how you implement it). Your event handler then uses that, but does not exit the process, that's the event loop's job. – mcarton May 15 '20 at 12:38
  • Hmm... now that you mention it it makes sense. Didn't think about that :) Thanks! – siannone May 15 '20 at 12:39

0 Answers0