diff --git a/src/main.tsx b/src/main.tsx index dd8278860..9e1ca9dfc 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -234,37 +234,58 @@ class Line extends React.Component<{sw : ScreenWindow, line : LineType, width : @mobxReact.observer class CmdInput extends React.Component<{}, {}> { + lastTab : boolean = false; + lastHistoryUpDown : boolean = false; lastTabCurLine : mobx.IObservableValue = mobx.observable.box(null); + textareaRef : React.RefObject = React.createRef(); + + isModKeyPress(e : any) { + return e.code.match(/^(Control|Meta|Alt|Shift)(Left|Right)$/); + } + + getLinePos(elem : any) : {numLines : number, linePos : number} { + let numLines = elem.value.split("\n").length; + let linePos = elem.value.substr(0, elem.selectionStart).split("\n").length; + return {numLines, linePos}; + } @mobx.action @boundMethod onKeyDown(e : any) { mobx.action(() => { + if (this.isModKeyPress(e)) { + return; + } let model = GlobalModel; let inputModel = model.inputModel; let win = model.getActiveWindow(); let ctrlMod = e.getModifierState("Control") || e.getModifierState("Meta") || e.getModifierState("Shift"); let curLine = inputModel.getCurLine(); - let ltCurLine = this.lastTabCurLine.get(); + + let lastTab = this.lastTab; + this.lastTab = (e.code == "Tab"); + let lastHist = this.lastHistoryUpDown; + this.lastHistoryUpDown = false; + if (e.code == "Tab") { e.preventDefault(); - let lastTab = (ltCurLine != null && curLine == ltCurLine); if (lastTab) { GlobalModel.submitCommand("compgen", null, [curLine], {"comppos": String(curLine.length), "compshow": "1", "nohist": "1"}); return; } else { - this.lastTabCurLine.set(curLine); GlobalModel.submitCommand("compgen", null, [curLine], {"comppos": String(curLine.length), "nohist": "1"}); GlobalModel.clearInfoMsg(true); return; } } - if (ltCurLine != null && curLine != ltCurLine) { - this.lastTabCurLine.set(null); - } - if (e.code == "Enter" && !ctrlMod) { + if (e.code == "Enter") { e.preventDefault(); - setTimeout(() => this.doSubmitCmd(), 0); + if (!ctrlMod) { + setTimeout(() => this.doSubmitCmd(), 0); + return; + } + e.target.setRangeText("\n", e.target.selectionStart, e.target.selectionEnd, "end"); + GlobalModel.inputModel.setCurLine(e.target.value); return; } if (e.code == "Escape") { @@ -277,15 +298,28 @@ class CmdInput extends React.Component<{}, {}> { inputModel.clearCurLine(); return; } - if (e.code == "ArrowUp") { - e.preventDefault(); - inputModel.prevHistoryItem(); - return; - } - if (e.code == "ArrowDown") { - e.preventDefault(); - inputModel.nextHistoryItem(); - return; + if (e.code == "ArrowUp" || e.code == "ArrowDown") { + let linePos = this.getLinePos(e.target); + if (e.code == "ArrowUp") { + if (!lastHist && linePos.linePos > 1) { + // regular arrow + return; + } + e.preventDefault(); + inputModel.prevHistoryItem(); + this.lastHistoryUpDown = true; + return; + } + if (e.code == "ArrowDown") { + if (!lastHist && linePos.linePos < linePos.numLines) { + // regular arrow + return; + } + e.preventDefault(); + inputModel.nextHistoryItem(); + this.lastHistoryUpDown = true; + return; + } } // console.log(e.code, e.keyCode, e.key, event.which, ctrlMod, e); })(); @@ -324,6 +358,11 @@ class CmdInput extends React.Component<{}, {}> { let model = GlobalModel; let inputModel = model.inputModel; let curLine = inputModel.getCurLine(); + let numLines = curLine.split("\n").length; + let displayLines = numLines; + if (displayLines > 5) { + displayLines = 5; + } let win = GlobalModel.getActiveWindow(); let ri : RemoteInstanceType = null; if (win != null) { @@ -384,7 +423,7 @@ class CmdInput extends React.Component<{}, {}> {
{promptStr}
- +
diff --git a/src/sh2.less b/src/sh2.less index f67fbc1c6..4193414f3 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -479,6 +479,8 @@ body .xterm .xterm-viewport { color: white; background-color: black; font-family: 'JetBrains Mono', monospace; + padding-bottom: calc(0.5em - 1px); + padding-top: calc(0.5em - 1px); &:active, &:focus { border-color: white !important;