{"action":"created","issue":{"url":"https://api.github.com/repos/crossterm-rs/crossterm/issues/284","repository_url":"https://api.github.com/repos/crossterm-rs/crossterm","labels_url":"https://api.github.com/repos/crossterm-rs/crossterm/issues/284/labels{/name}","comments_url":"https://api.github.com/repos/crossterm-rs/crossterm/issues/284/comments","events_url":"https://api.github.com/repos/crossterm-rs/crossterm/issues/284/events","html_url":"https://github.com/crossterm-rs/crossterm/pull/284","id":511281848,"node_id":"MDExOlB1bGxSZXF1ZXN0MzMxNTA4MTEy","number":284,"title":"[WIP] Input Rewrite","user":{"login":"TimonPost","id":19969910,"node_id":"MDQ6VXNlcjE5OTY5OTEw","avatar_url":"https://avatars3.githubusercontent.com/u/19969910?v=4","gravatar_id":"","url":"https://api.github.com/users/TimonPost","html_url":"https://github.com/TimonPost","followers_url":"https://api.github.com/users/TimonPost/followers","following_url":"https://api.github.com/users/TimonPost/following{/other_user}","gists_url":"https://api.github.com/users/TimonPost/gists{/gist_id}","starred_url":"https://api.github.com/users/TimonPost/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TimonPost/subscriptions","organizations_url":"https://api.github.com/users/TimonPost/orgs","repos_url":"https://api.github.com/users/TimonPost/repos","events_url":"https://api.github.com/users/TimonPost/events{/privacy}","received_events_url":"https://api.github.com/users/TimonPost/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2019-10-23T12:13:47Z","updated_at":"2019-11-07T11:22:20Z","closed_at":null,"author_association":"COLLABORATOR","pull_request":{"url":"https://api.github.com/repos/crossterm-rs/crossterm/pulls/284","html_url":"https://github.com/crossterm-rs/crossterm/pull/284","diff_url":"https://github.com/crossterm-rs/crossterm/pull/284.diff","patch_url":"https://github.com/crossterm-rs/crossterm/pull/284.patch"},"body":"**Note, this design is not accurate anymore. Please have a look further into the discussion.**\r\n\r\n## New\r\n- Introduced the things discussed [here](https://github.com/crossterm-rs/crossterm/issues/257#issuecomment-539403231). It already addresses some of your comments. There is still some work left for this to be finished. I would like to hear your ideas on how to future envolve this?\r\n- Removes `Terminalnput` because it would become boilerplate code.\r\n- Introduces: ~`EventChannel`~, ~`EventConsumer`~, `EventPool`, ~`EventIterator`~, `EventSource`.\r\n- ~Allows iterating specific events.~\r\n- Allows swapping out event source (testing)\r\n- ~Introduces a single producer multiple consumer idea for input sharing~\r\n\r\n_usage example_\r\n```rust\r\nuse crossterm::{event_stream, poll_event, RawScreen};\r\n\r\nfn main () {\r\n    let r = RawScreen::into_raw_mode().unwrap();\r\n\r\n    let mut stream = event_stream();\r\n\r\n    while true {\r\n        poll_event();\r\n\r\n        for event in stream.key_events() {\r\n            println!(\"{:?}\", event);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n~## Area of Discussion:~\r\n\r\n~- Should we store local cache in `EventStream`? The idea behind this is that when reading from the channel we drain the events at the same time? When we read we can store them locally so that we can consume them later on and no events will be lost when for example the user uses `InputStream::key_events` first and then `InputStream::events()`.~\r\n~- Should the poll function only read a single event or read everything available in the buffers.~\r\n\r\n~## Todo~\r\n\r\n- [ ] implement mouse event enable/disable\r\n- [ ] implement read line\r\n- [ ] More tests\r\n- [ ] Documentation\r\n\r\n~## Diagram:~\r\n\r\n![image](https://user-images.githubusercontent.com/19969910/67392214-6df73200-f5a0-11e9-9949-ff27cb8d8aaa.png)\r\n\r\n\r\n## Definitions\r\n\r\n### SPMC\r\n~I use shrev `EventChannel` for this, this channel can have multiple readers and a single writer. This is exactly what we want. I tried with normal MPMC channels before, but this didn't work out well. It required a lot of manual thread-safe work like putting everything in arc, mutexes, etc.~\r\n\r\n\r\n### Event Pool\r\n\r\n**EventPool** \r\n\r\n- It is stored statically in with `lazy static`, there should only be one instance of this pool. \r\n~- It is the owner of the SPMC channel.~\r\n- It is the only one allowed to grant read/write access to the owned event channel.\r\n~- It can create multiple consumers and a single producer. ~\r\n- Access to `EventPool` is secured with `RwLock`. Therefore consumers can be created while a write lock is obtained. \r\n~- Behaves similar to `Stdin`~\r\n- Only reads a single input event on `poll`. This allows the user to create its own async wrapper. The \r\n\r\n~**EventPoolReadLock**~\r\n\r\n~- Provides read access to the `EventPool`~\r\n\r\n**EventPoolWriteLock**\r\n\r\n- Provides write access to `EventPool`\r\n\r\n~**event_stream**~\r\n\r\n~-A static function that returns an event stream that can be used to read input events with.~\r\n\r\n**poll_event**\r\n\r\n~A static function that polls for input from the underlying input source.\r\nAn input event will be replicated to all consumers aka streams if an input event has occurred.\r\nThis poll function will block read for a single keypress.~\r\n\r\n### Input Source\r\n`InputPool` has one input source. This input source can be anything. In the tests I use the `FakeInputSource`, this allows us to fake input data, this might be useful for the user as well for testing it's application. \r\n\r\n- An input source does a block read for one key event. \r\n- Input source is called by `InputPool::poll()`\r\n\r\nThe PR contains three input sources: `TtyEventSource`, `WinApiEventSource`, `FakeEventSource`\r\n\r\n~### Event Stream~\r\n\r\n~- Has it's own SPMC consumer, can't write, only read.~\r\n~- It can iterate specifically over certain events, like a mouse, keyboard. This is a great feature I like to support. Because most often people only want to read for up, down, left, right arrows for example.~\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/crossterm-rs/crossterm/issues/comments/551038358","html_url":"https://github.com/crossterm-rs/crossterm/pull/284#issuecomment-551038358","issue_url":"https://api.github.com/repos/crossterm-rs/crossterm/issues/284","id":551038358,"node_id":"MDEyOklzc3VlQ29tbWVudDU1MTAzODM1OA==","user":{"login":"zrzka","id":1084172,"node_id":"MDQ6VXNlcjEwODQxNzI=","avatar_url":"https://avatars1.githubusercontent.com/u/1084172?v=4","gravatar_id":"","url":"https://api.github.com/users/zrzka","html_url":"https://github.com/zrzka","followers_url":"https://api.github.com/users/zrzka/followers","following_url":"https://api.github.com/users/zrzka/following{/other_user}","gists_url":"https://api.github.com/users/zrzka/gists{/gist_id}","starred_url":"https://api.github.com/users/zrzka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zrzka/subscriptions","organizations_url":"https://api.github.com/users/zrzka/orgs","repos_url":"https://api.github.com/users/zrzka/repos","events_url":"https://api.github.com/users/zrzka/events{/privacy}","received_events_url":"https://api.github.com/users/zrzka/received_events","type":"User","site_admin":false},"created_at":"2019-11-07T11:22:20Z","updated_at":"2019-11-07T11:22:20Z","author_association":"MEMBER","body":"@TimonPost I started writing comments, but there were lot of them. Decided to do a review in another form. Check [this PR](https://github.com/crossterm-rs/crossterm/pull/312) and all my commits. A bit of everything there. Or just ...\r\n\r\n```bash\r\n$ git diff remotes/origin/input_rewrite..remotes/origin/zrzka/input_rewrite_comments\r\n```\r\n\r\nIt's a **1st round**, to make it compile, remove warnings, pass CI, clippy, ..."}}
{"actor":{"display_login":"zrzka"}}