From a12ae333f682e7cc6c47885336c8abc0a38b03aa Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 21 Dec 2022 11:12:34 -0600 Subject: [PATCH 1/3] yarn: revert xterm to 5.0.0 xterm v5.1.0 broke scrolling so we lock in v5.0.0 for now. --- CHANGELOG.md | 5 +++++ package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1fd02b..8b8f7817 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ## [Unreleased] +### Fixed +- Fixed terminal scroll not working ([support#866]). + +[support#866]: https://github.com/pybricks/support/issues/866 + ## [2.0.0] - 2022-12-20 ### Added diff --git a/package.json b/package.json index 9483dacc..4dad9486 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "webpack-dev-server": "^4.11.1", "webpack-manifest-plugin": "^5.0.0", "workbox-webpack-plugin": "^6.5.4", - "xterm": "^5.1.0", + "xterm": "5.0.0", "xterm-addon-fit": "^0.6.0", "zen-push": "^0.3.1" }, diff --git a/yarn.lock b/yarn.lock index 7e4fbbe7..d9db3238 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2535,7 +2535,7 @@ __metadata: webpack-dev-server: ^4.11.1 webpack-manifest-plugin: ^5.0.0 workbox-webpack-plugin: ^6.5.4 - xterm: ^5.1.0 + xterm: 5.0.0 xterm-addon-fit: ^0.6.0 zen-push: ^0.3.1 languageName: unknown @@ -15902,10 +15902,10 @@ __metadata: languageName: node linkType: hard -"xterm@npm:^5.1.0": - version: 5.1.0 - resolution: "xterm@npm:5.1.0" - checksum: cbacbc9dc1bbcf21dabecff46856b43f2d5854b42c1bec4ea03a5720000f2a88d79b0da45b6c38213d6607474a1fbe66d5ff25fa120b7e9e60eeed964dd840a1 +"xterm@npm:5.0.0": + version: 5.0.0 + resolution: "xterm@npm:5.0.0" + checksum: c2f1d02a708d3d02bebf052dfdf54ecd1b619386bed8f27ed42483d398a3e0bc3595fc855c600db99fd3a91f6d3e8feabe118f1f8f14bbed92d8b3d77277ab92 languageName: node linkType: hard From 23db8f4d9b099c0e0fcfd795376c3333a1b5f80c Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 21 Dec 2022 12:29:14 -0600 Subject: [PATCH 2/3] terminal: fix input handler loop getting stuck When no hub is connected, the terminal input handler loop would get stuck waiting for didWrite or didFailToWrite which would never come because handleWriteUart in ble/sagas only runs when a hub is connected. This is fixed by only dispatching a write action if a user program is running on the hub. By using this state, it also fixes characters being buffered before the user program starts, e.g. - connect hub - type into terminal - no echo - start the repl - previously typed characters are echoed after the repl prompt Now, anything typed before the user program is just ignored. Fixes: https://github.com/pybricks/support/issues/865 Also properly fixes https://github.com/pybricks/support/issues/303 --- CHANGELOG.md | 2 ++ src/terminal/sagas.test.ts | 15 +++++++++++++++ src/terminal/sagas.ts | 17 +++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b8f7817..96b54e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ ### Fixed - Fixed terminal scroll not working ([support#866]). +- Fixed terminal breaks if input is given before hub is connected ([support#865]). +[support#865]: https://github.com/pybricks/support/issues/865 [support#866]: https://github.com/pybricks/support/issues/866 ## [2.0.0] - 2022-12-20 diff --git a/src/terminal/sagas.test.ts b/src/terminal/sagas.test.ts index 07ffcf2b..0bab0da5 100644 --- a/src/terminal/sagas.test.ts +++ b/src/terminal/sagas.test.ts @@ -71,6 +71,7 @@ describe('Terminal data source responds to receive data actions', () => { test('basic function works', async () => { const saga = new AsyncSaga(terminal, { nextMessageId: createCountFunc() }); + saga.updateState({ hub: { runtime: HubRuntimeState.Running } }); saga.put(receiveData('test1234')); @@ -82,6 +83,7 @@ describe('Terminal data source responds to receive data actions', () => { test('messages are queued until previous has completed', async () => { const saga = new AsyncSaga(terminal, { nextMessageId: createCountFunc() }); + saga.updateState({ hub: { runtime: HubRuntimeState.Running } }); saga.put(receiveData('test1234')); await delay(50); // without delay, messages are combined @@ -108,6 +110,7 @@ describe('Terminal data source responds to receive data actions', () => { test('messages are queued until previous has failed', async () => { const saga = new AsyncSaga(terminal, { nextMessageId: createCountFunc() }); + saga.updateState({ hub: { runtime: HubRuntimeState.Running } }); saga.put(receiveData('test1234')); await delay(50); // without delay, messages are combined @@ -134,6 +137,7 @@ describe('Terminal data source responds to receive data actions', () => { test('small messages are combined', async () => { const saga = new AsyncSaga(terminal, { nextMessageId: createCountFunc() }); + saga.updateState({ hub: { runtime: HubRuntimeState.Running } }); saga.put(receiveData('test1234')); saga.put(receiveData('test1234')); @@ -148,6 +152,7 @@ describe('Terminal data source responds to receive data actions', () => { const testData = '012345678901234567890123456789'; const saga = new AsyncSaga(terminal, { nextMessageId: createCountFunc() }); + saga.updateState({ hub: { runtime: HubRuntimeState.Running } }); saga.put(receiveData(testData)); @@ -163,4 +168,14 @@ describe('Terminal data source responds to receive data actions', () => { await saga.end(); }); + + test('if user program is not running, do not dispatch write', async () => { + const saga = new AsyncSaga(terminal, { nextMessageId: createCountFunc() }); + saga.updateState({ hub: { runtime: HubRuntimeState.Disconnected } }); + + saga.put(receiveData('test1234')); + + // line below will fail with unhandled pending dispatches if not working correctly + await saga.end(); + }); }); diff --git a/src/terminal/sagas.ts b/src/terminal/sagas.ts index 0a6442bd..ae0ee9ef 100644 --- a/src/terminal/sagas.ts +++ b/src/terminal/sagas.ts @@ -49,8 +49,10 @@ function* receiveUartData(action: ReturnType): Generator { } function* receiveTerminalData(): Generator { + const nextMessageId = yield* getContext<() => number>('nextMessageId'); const channel = yield* actionChannel(receiveData); - while (true) { + + for (;;) { // wait for input from terminal const action = yield* take(channel); let value = action.value; @@ -68,10 +70,21 @@ function* receiveTerminalData(): Generator { value += action.value; } - const nextMessageId = yield* getContext<() => number>('nextMessageId'); + const isUserProgramRunning = yield* select( + (s: RootState) => s.hub.runtime === HubRuntimeState.Running, + ); + + // REVISIT: this test is a bit dangerous since it is not actually + // testing that handleWriteUart in ble/sagas is running. In theory + // it should be fine as long a the logic for the state doesn't change. + if (!isUserProgramRunning) { + // if no user program is running, input goes to /dev/null + continue; + } // stdin gets piped to BLE connection const data = encoder.encode(value); + for (let i = 0; i < data.length; i += nordicUartSafeTxCharLength) { const { id } = yield* put( write(nextMessageId(), data.slice(i, i + nordicUartSafeTxCharLength)), From ef81bb2341767c1095fbab7cb1916f4fea08238e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 21 Dec 2022 13:27:33 -0600 Subject: [PATCH 3/3] v2.0.1 --- CHANGELOG.md | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b54e95..9200913d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ## [Unreleased] +## [2.0.1] - 2022-12-21 + ### Fixed - Fixed terminal scroll not working ([support#866]). - Fixed terminal breaks if input is given before hub is connected ([support#865]). @@ -627,7 +629,8 @@ Prerelease changes are documented at [support#48]. -[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0...HEAD +[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.1...HEAD +[2.0.1]: https://github.com/pybricks/pybricks-code/compare/v2.0.0...v2.0.1 [2.0.0]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-rc.1...v2.0.0 [2.0.0-rc.1]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.12...v2.0.0-rc.1 [2.0.0-beta.12]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.11...v2.0.0-beta.12 diff --git a/package.json b/package.json index 4dad9486..3d80b8c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pybricks/pybricks-code", - "version": "2.0.0", + "version": "2.0.1", "license": "MIT", "author": "The Pybricks Authors", "repository": {