diff --git a/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx b/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx index f96636455..1211aad09 100644 --- a/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx +++ b/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx @@ -6,6 +6,74 @@ import { BoardsServiceProvider } from '../../boards/boards-service-provider'; import { MonitorModel } from '../../monitor-model'; import { Unknown } from '../../../common/nls'; +class RingList { + private ring: string[]; + private size: number; + private begin: number; + private index: number; + private end: number; + + constructor(size: number = 100) { + this.init = this.init.bind(this); + this.push = this.push.bind(this); + this.prev = this.prev.bind(this); + this.next = this.next.bind(this); + this.init(size); + } + + private init(size: number = 100) + { + this.ring = []; + this.size = (size > 0) ? size : 1; + this.begin = 0; + this.index = 0; + this.end = -1; + } + + push(val: string): number { + this.end++; + if (this.ring.length >= this.size) + { + if (this.end >= this.size) + this.end = 0; + if (this.end === this.begin) + { + this.begin++; + if (this.begin >= this.size) + this.begin = 0; + } + } + this.ring[this.end] = val; + this.index = this.end; + + return this.index; + } + + prev(): string { + if (this.ring.length < 1) { + return ''; + } + + if (this.index !== this.begin) { + this.index = (this.index > 0) ? --this.index : this.size - 1; + } + + return this.ring[this.index]; + } + + next(): string { + if (this.ring.length < 1) { + return ''; + } + + if (this.index !== this.end) { + this.index = (++this.index < this.size) ? this.index : 0; + } + + return this.ring[this.index]; + } +} + export namespace SerialMonitorSendInput { export interface Props { readonly boardsServiceProvider: BoardsServiceProvider; @@ -16,6 +84,7 @@ export namespace SerialMonitorSendInput { export interface State { text: string; connected: boolean; + history: RingList; } } @@ -27,7 +96,7 @@ export class SerialMonitorSendInput extends React.Component< constructor(props: Readonly) { super(props); - this.state = { text: '', connected: true }; + this.state = { text: '', connected: true, history: new RingList() }; this.onChange = this.onChange.bind(this); this.onSend = this.onSend.bind(this); this.onKeyDown = this.onKeyDown.bind(this); @@ -110,7 +179,19 @@ export class SerialMonitorSendInput extends React.Component< if (keyCode) { const { key } = keyCode; if (key === Key.ENTER) { + // NOTE: order of operations is critical here. Push the current state.text + // onto the history stack before sending. After sending, state.text is empty + // and you'd end up pushing '' onto the history stack. + if (this.state.text.length > 0) { + this.state.history.push(this.state.text); + } this.onSend(); + } + else if (key === Key.ARROW_UP) { + this.setState({ text: this.state.history.prev()}); + } + else if (key === Key.ARROW_DOWN) { + this.setState({ text: this.state.history.next()}); } } }