crossterm-rs / crossterm

Cross platform terminal library rust
MIT License
3.27k stars 279 forks source link

Add Event::Terminate #554

Open Riey opened 3 years ago

Riey commented 3 years ago

Is your feature request related to a problem? Please describe.

Terminal program often face to SIGINT, SIGTERM and I think it's common to write handler for these signals

so I have to use another crate like ctrl_c however crossterm already can do it will fit well with existing event loop

Describe the solution you'd like

Add new event variant for those termination signals Event::Exit, Event::Terminate, ... whatever

Describe alternatives you've considered in any

Additional context

I have no idea how windows can make this event

TimonPost commented 3 years ago

We could do that, but what do we do if someone wants to use CTRL + C with a other use case in mind?

Riey commented 3 years ago

CTRL + C doesn't affected if someone want to use CTRL + C as KeyEvent they already use raw mode and it doesn't trigger SIGINT by key stroke

mainrs commented 3 years ago

This sounds really useful! I already do have to register a custom hook in almost all of the CLIs I have, this would (at least for me :) ) reduce boilerplate :)

TimonPost commented 3 years ago

@Riey okay. It would be nice to have. Sounds very usefull.

pickfire commented 3 years ago

And suspend as well.

yunlingz commented 3 years ago

It would be very useful to have POSIX signal events like SIGCONT, SIGINT, SIGTSTP....

How about a new event type Event::Signal(libc::c_int) ?

Without signal events, it's very very difficult and tricky to implement job controlling for crossterm-based tui app, such as using ctrl-z to suspend the app to background and using fg to bring it back to front.

pickfire commented 3 years ago

libc:c_int is a bit overkill and less safe, ideally it should be an enum of signals exposed from signal-hook maybe. Yeah, I am trying to do ctrl-z as well and it seemed like the only method now is to manually implement signal-hook ourselves.

yunlingz commented 3 years ago

For now, I can only implement ctrl-z like this, and suspending does work. But restoring by fg is not possible, since it relies on SIGCONT signal.

Similar feature request has been proposed by #494 already.

Event::Key(KeyEvent {
    code: kcode,
    modifiers: KeyModifiers::CONTROL,
}) => match kcode {
    KeyCode::Char('c') => break,
    KeyCode::Char('z') => {
        execute!(
            terminal.backend_mut(),
            LeaveAlternateScreen,
            cursor::Show,
        )
        .unwrap();
        disable_raw_mode().unwrap();
        unsafe { libc::raise(libc::SIGTSTP) };
    }
    _ => {}
},
mainrs commented 3 years ago

How would this feature be handled on Windows? Does Windows support a backgorund signal or an equivalent feature for sending a process into the background? :thinking:

pickfire commented 2 years ago

Helix did get suspend to work by using signal-hook-tokio https://github.com/helix-editor/helix/blob/9400d743075375e9c9ad90cc91c5530445d8c304/helix-term/src/application.rs#L255-L270, but not sure why disable_raw_mode does not seemed to disable stuff cleanly that in git commit when I suspend the raw mode still seemed to be there (I can't really check) but when I removed both enable_raw_mode and disable_raw_mode suspend works correctly.

Ben-PH commented 1 year ago

I'm making a tui using an actor model: each actor has a channel to send data to the main event loop, which iterates over data from actors as they come in.

One of those actors is the crossterm event reader.

One of the things I need to consider is graceful shutdown. If the system gets a sig-int (physical ctrl-c, triggered by the OS, or whatever) I would like to be able to get my actors to shutdown gracefully.

My xterm system is basically this, spawned in a dedicated thread:

loop {
    term_ev_tx
        .send(event::read())
        .expect("Todo: setup channel failure story");
}

The problem here, is that once the thread is blocked on read, it's only means of exit is an actual terminal event, or process cleanup.

Some sort of mechanism to be unblocked by the library user, such as a Condvar or similar, would be an awesome feature.