diff --git a/terminus-serial/package.json b/terminus-serial/package.json index 5980eaec..25c9889c 100644 --- a/terminus-serial/package.json +++ b/terminus-serial/package.json @@ -20,6 +20,7 @@ "@types/node": "14.14.14", "@types/ssh2": "^0.5.35", "ansi-colors": "^4.1.1", + "buffer-replace": "^1.0.0", "cli-spinner": "^0.2.10" }, "peerDependencies": { diff --git a/terminus-serial/src/api.ts b/terminus-serial/src/api.ts index 89823f39..1754c707 100644 --- a/terminus-serial/src/api.ts +++ b/terminus-serial/src/api.ts @@ -1,4 +1,5 @@ import stripAnsi from 'strip-ansi' +import bufferReplace from 'buffer-replace' import { BaseSession } from 'terminus-terminal' import { SerialPort } from 'serialport' import { Logger } from 'terminus-core' @@ -28,6 +29,8 @@ export interface SerialConnection { scripts?: LoginScript[] color?: string inputMode?: InputMode + inputNewlines?: NewlineMode + outputNewlines?: NewlineMode } export const BAUD_RATES = [ @@ -40,6 +43,7 @@ export interface SerialPortInfo { } export type InputMode = null | 'readline' +export type NewlineMode = null | 'cr' | 'lf' | 'crlf' export class SerialSession extends BaseSession { scripts?: LoginScript[] @@ -136,7 +140,23 @@ export class SerialSession extends BaseSession { return null } + private replaceNewlines (data: Buffer, mode?: NewlineMode): Buffer { + if (!mode) { + return data + } + data = bufferReplace(data, '\r\n', '\n') + data = bufferReplace(data, '\r', '\n') + const replacement = { + strip: '', + cr: '\r', + lf: '\n', + crlf: '\r\n', + }[mode] + return bufferReplace(data, '\n', replacement) + } + private onInput (data: Buffer) { + data = this.replaceNewlines(data, this.connection.inputNewlines) if (this.serial) { this.serial.write(data.toString()) } @@ -163,6 +183,8 @@ export class SerialSession extends BaseSession { this.inputPromptVisible = false } } + + data = this.replaceNewlines(data, this.connection.outputNewlines) this.emitOutput(data) if (this.scripts) { diff --git a/terminus-serial/src/components/editConnectionModal.component.pug b/terminus-serial/src/components/editConnectionModal.component.pug index c7f12ca5..5fe292f3 100644 --- a/terminus-serial/src/components/editConnectionModal.component.pug +++ b/terminus-serial/src/components/editConnectionModal.component.pug @@ -30,26 +30,67 @@ ) option([value]='x', *ngFor='let x of baudRates') {{x}} - .form-line - .header - .title Input mode + .row + .col-6 + .form-line + .header + .title Input mode - .d-flex(ngbDropdown) - button.btn.btn-secondary.btn-tab-bar( - ngbDropdownToggle, - ) {{getInputModeName(connection.inputMode)}} + .d-flex(ngbDropdown) + button.btn.btn-secondary.btn-tab-bar( + ngbDropdownToggle, + ) {{getInputModeName(connection.inputMode)}} - div(ngbDropdownMenu) - a.d-flex.flex-column( - *ngFor='let mode of inputModes', - (click)='connection.inputMode = mode.key', - ngbDropdownItem + div(ngbDropdownMenu) + a.d-flex.flex-column( + *ngFor='let mode of inputModes', + (click)='connection.inputMode = mode.key', + ngbDropdownItem + ) + div {{mode.name}} + .text-muted {{mode.description}} + + .col-6 + .form-line + .header + .title Input newlines + + select.form-control( + [(ngModel)]='connection.inputNewlines', ) - div {{mode.name}} - .text-muted {{mode.description}} + option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}} + .row + .col-6 + //- .form-line + .header + .title Output mode - ngb-tab(id='advanced') + .d-flex(ngbDropdown) + button.btn.btn-secondary.btn-tab-bar( + ngbDropdownToggle, + ) {{getInputModeName(connection.inputMode)}} + + div(ngbDropdownMenu) + a.d-flex.flex-column( + *ngFor='let mode of inputModes', + (click)='connection.inputMode = mode.key', + ngbDropdownItem + ) + div {{mode.name}} + .text-muted {{mode.description}} + + .col-6 + .form-line + .header + .title Output newlines + + select.form-control( + [(ngModel)]='connection.outputNewlines', + ) + option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}} + + ngb-tab(id='advanced') ng-template(ngbTabTitle) Advanced ng-template(ngbTabContent) .form-line diff --git a/terminus-serial/src/components/editConnectionModal.component.ts b/terminus-serial/src/components/editConnectionModal.component.ts index ee139c79..64af510a 100644 --- a/terminus-serial/src/components/editConnectionModal.component.ts +++ b/terminus-serial/src/components/editConnectionModal.component.ts @@ -19,6 +19,13 @@ export class EditConnectionModalComponent { { key: null, name: 'Normal', description: 'Input is sent as you type' }, { key: 'readline', name: 'Line by line', description: 'Line editor, input is sent after you press Enter' }, ] + newlineModes = [ + { key: null, name: 'Keep' }, + { key: 'strip', name: 'Strip' }, + { key: 'cr', name: 'Force CR' }, + { key: 'lf', name: 'Force LF' }, + { key: 'crlf', name: 'Force CRLF' }, + ] constructor ( private modalInstance: NgbActiveModal, diff --git a/terminus-serial/src/components/serialSettingsTab.component.ts b/terminus-serial/src/components/serialSettingsTab.component.ts index 2dcce9ed..4def0735 100644 --- a/terminus-serial/src/components/serialSettingsTab.component.ts +++ b/terminus-serial/src/components/serialSettingsTab.component.ts @@ -34,7 +34,9 @@ export class SerialSettingsTabComponent { xany: false, xoff: false, xon: false, - inputMode: null + inputMode: null, + inputNewlines: null, + outputNewlines: null, } const modal = this.ngbModal.open(EditConnectionModalComponent) diff --git a/terminus-serial/yarn.lock b/terminus-serial/yarn.lock index f3b4cec5..6db92f47 100644 --- a/terminus-serial/yarn.lock +++ b/terminus-serial/yarn.lock @@ -32,6 +32,11 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +buffer-replace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-replace/-/buffer-replace-1.0.0.tgz#bc427c40af4c1f06d6933dede57110acba8ade54" + integrity sha1-vEJ8QK9MHwbWkz3t5XEQrLqK3lQ= + cli-spinner@^0.2.10: version "0.2.10" resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"