mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-26 06:19:53 +00:00
serial newline modes
This commit is contained in:
parent
dd2d2ce20d
commit
43a27a7b7c
@ -20,6 +20,7 @@
|
|||||||
"@types/node": "14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"@types/ssh2": "^0.5.35",
|
"@types/ssh2": "^0.5.35",
|
||||||
"ansi-colors": "^4.1.1",
|
"ansi-colors": "^4.1.1",
|
||||||
|
"buffer-replace": "^1.0.0",
|
||||||
"cli-spinner": "^0.2.10"
|
"cli-spinner": "^0.2.10"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import stripAnsi from 'strip-ansi'
|
import stripAnsi from 'strip-ansi'
|
||||||
|
import bufferReplace from 'buffer-replace'
|
||||||
import { BaseSession } from 'terminus-terminal'
|
import { BaseSession } from 'terminus-terminal'
|
||||||
import { SerialPort } from 'serialport'
|
import { SerialPort } from 'serialport'
|
||||||
import { Logger } from 'terminus-core'
|
import { Logger } from 'terminus-core'
|
||||||
@ -28,6 +29,8 @@ export interface SerialConnection {
|
|||||||
scripts?: LoginScript[]
|
scripts?: LoginScript[]
|
||||||
color?: string
|
color?: string
|
||||||
inputMode?: InputMode
|
inputMode?: InputMode
|
||||||
|
inputNewlines?: NewlineMode
|
||||||
|
outputNewlines?: NewlineMode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BAUD_RATES = [
|
export const BAUD_RATES = [
|
||||||
@ -40,6 +43,7 @@ export interface SerialPortInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type InputMode = null | 'readline'
|
export type InputMode = null | 'readline'
|
||||||
|
export type NewlineMode = null | 'cr' | 'lf' | 'crlf'
|
||||||
|
|
||||||
export class SerialSession extends BaseSession {
|
export class SerialSession extends BaseSession {
|
||||||
scripts?: LoginScript[]
|
scripts?: LoginScript[]
|
||||||
@ -136,7 +140,23 @@ export class SerialSession extends BaseSession {
|
|||||||
return null
|
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) {
|
private onInput (data: Buffer) {
|
||||||
|
data = this.replaceNewlines(data, this.connection.inputNewlines)
|
||||||
if (this.serial) {
|
if (this.serial) {
|
||||||
this.serial.write(data.toString())
|
this.serial.write(data.toString())
|
||||||
}
|
}
|
||||||
@ -163,6 +183,8 @@ export class SerialSession extends BaseSession {
|
|||||||
this.inputPromptVisible = false
|
this.inputPromptVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data = this.replaceNewlines(data, this.connection.outputNewlines)
|
||||||
this.emitOutput(data)
|
this.emitOutput(data)
|
||||||
|
|
||||||
if (this.scripts) {
|
if (this.scripts) {
|
||||||
|
@ -30,26 +30,67 @@
|
|||||||
)
|
)
|
||||||
option([value]='x', *ngFor='let x of baudRates') {{x}}
|
option([value]='x', *ngFor='let x of baudRates') {{x}}
|
||||||
|
|
||||||
.form-line
|
.row
|
||||||
.header
|
.col-6
|
||||||
.title Input mode
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Input mode
|
||||||
|
|
||||||
.d-flex(ngbDropdown)
|
.d-flex(ngbDropdown)
|
||||||
button.btn.btn-secondary.btn-tab-bar(
|
button.btn.btn-secondary.btn-tab-bar(
|
||||||
ngbDropdownToggle,
|
ngbDropdownToggle,
|
||||||
) {{getInputModeName(connection.inputMode)}}
|
) {{getInputModeName(connection.inputMode)}}
|
||||||
|
|
||||||
div(ngbDropdownMenu)
|
div(ngbDropdownMenu)
|
||||||
a.d-flex.flex-column(
|
a.d-flex.flex-column(
|
||||||
*ngFor='let mode of inputModes',
|
*ngFor='let mode of inputModes',
|
||||||
(click)='connection.inputMode = mode.key',
|
(click)='connection.inputMode = mode.key',
|
||||||
ngbDropdownItem
|
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}}
|
option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}}
|
||||||
.text-muted {{mode.description}}
|
|
||||||
|
|
||||||
|
.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(ngbTabTitle) Advanced
|
||||||
ng-template(ngbTabContent)
|
ng-template(ngbTabContent)
|
||||||
.form-line
|
.form-line
|
||||||
|
@ -19,6 +19,13 @@ export class EditConnectionModalComponent {
|
|||||||
{ key: null, name: 'Normal', description: 'Input is sent as you type' },
|
{ 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' },
|
{ 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 (
|
constructor (
|
||||||
private modalInstance: NgbActiveModal,
|
private modalInstance: NgbActiveModal,
|
||||||
|
@ -34,7 +34,9 @@ export class SerialSettingsTabComponent {
|
|||||||
xany: false,
|
xany: false,
|
||||||
xoff: false,
|
xoff: false,
|
||||||
xon: false,
|
xon: false,
|
||||||
inputMode: null
|
inputMode: null,
|
||||||
|
inputNewlines: null,
|
||||||
|
outputNewlines: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
const modal = this.ngbModal.open(EditConnectionModalComponent)
|
const modal = this.ngbModal.open(EditConnectionModalComponent)
|
||||||
|
@ -32,6 +32,11 @@ ansi-colors@^4.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
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:
|
cli-spinner@^0.2.10:
|
||||||
version "0.2.10"
|
version "0.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
|
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user