diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index cbb8e14a44e..317f703cacf 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -33,7 +33,7 @@ import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/w import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { Direction, ICreateTerminalOptions, IDetachedTerminalInstance, ITerminalConfigHelper, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; -import { IRemoteTerminalAttachTarget, ITerminalProfileResolverService, ITerminalProfileService, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IRemoteTerminalAttachTarget, ITerminalProfileResolverService, ITerminalProfileService, TERMINAL_VIEW_ID, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { createProfileSchemaEnums } from 'vs/platform/terminal/common/terminalProfiles'; import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; @@ -928,25 +928,45 @@ export function registerTerminalActions() { registerActiveInstanceAction({ id: TerminalCommandId.ScrollToPreviousCommand, - title: { value: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), original: 'Scroll To Previous Command' }, + title: terminalStrings.scrollToPreviousCommand, keybinding: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow, when: ContextKeyExpr.and(TerminalContextKeys.focus, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), + icon: Codicon.arrowUp, + menu: [ + { + id: MenuId.ViewTitle, + group: 'navigation', + order: 4, + when: ContextKeyExpr.equals('view', TERMINAL_VIEW_ID), + isHiddenByDefault: true + } + ], run: (activeInstance) => activeInstance.xterm?.markTracker.scrollToPreviousMark(undefined, undefined, activeInstance.capabilities.has(TerminalCapability.CommandDetection)) }); registerActiveInstanceAction({ id: TerminalCommandId.ScrollToNextCommand, - title: { value: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"), original: 'Scroll To Next Command' }, + title: terminalStrings.scrollToNextCommand, keybinding: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow, when: ContextKeyExpr.and(TerminalContextKeys.focus, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), + icon: Codicon.arrowDown, + menu: [ + { + id: MenuId.ViewTitle, + group: 'navigation', + order: 4, + when: ContextKeyExpr.equals('view', TERMINAL_VIEW_ID), + isHiddenByDefault: true + } + ], run: (activeInstance) => { activeInstance.xterm?.markTracker.scrollToNextMark(); activeInstance.focus(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts b/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts index dfdaa699110..4eb3ae8c048 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts @@ -515,7 +515,7 @@ export function setupTerminalMenus(): void { title: localize('workbench.action.terminal.clearLong', "Clear Terminal"), icon: Codicon.clearAll }, - group: 'navigation', + group: 'execute', order: 4, when: ContextKeyExpr.equals('view', TERMINAL_VIEW_ID), isHiddenByDefault: true @@ -529,7 +529,7 @@ export function setupTerminalMenus(): void { title: localize('workbench.action.terminal.runActiveFile', "Run Active File"), icon: Codicon.run }, - group: 'navigation', + group: 'execute', order: 5, when: ContextKeyExpr.equals('view', TERMINAL_VIEW_ID), isHiddenByDefault: true @@ -543,7 +543,7 @@ export function setupTerminalMenus(): void { title: localize('workbench.action.terminal.runSelectedText', "Run Selected Text"), icon: Codicon.selection }, - group: 'navigation', + group: 'execute', order: 6, when: ContextKeyExpr.equals('view', TERMINAL_VIEW_ID), isHiddenByDefault: true diff --git a/src/vs/workbench/contrib/terminal/common/terminalStrings.ts b/src/vs/workbench/contrib/terminal/common/terminalStrings.ts index abcfa9fb57c..ebe0795a239 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalStrings.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalStrings.ts @@ -85,5 +85,13 @@ export const terminalStrings = { stickyScroll: { value: localize('stickyScroll', "Sticky Scroll"), original: 'Sticky Scroll' + }, + scrollToPreviousCommand: { + value: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), + original: 'Scroll To Previous Command' + }, + scrollToNextCommand: { + value: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"), + original: 'Scroll To Next Command' } }; diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts index 3f0a9d7c0a0..a54e52081e0 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts @@ -7,12 +7,10 @@ import type { SerializeAddon as SerializeAddonType } from '@xterm/addon-serializ import type { IBufferLine, IMarker, ITerminalOptions, ITheme, Terminal as RawXtermTerminal, Terminal as XTermTerminal } from '@xterm/xterm'; import { importAMDNodeModule } from 'vs/amdX'; import { $, addDisposableListener, addStandardDisposableListener, getWindow } from 'vs/base/browser/dom'; -import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; import { debounce, memoize, throttle } from 'vs/base/common/decorators'; import { Event } from 'vs/base/common/event'; import { Disposable, MutableDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { OS } from 'vs/base/common/platform'; import 'vs/css!./media/stickyScroll'; import { localize } from 'vs/nls'; import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; @@ -27,7 +25,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITerminalInstance, IXtermColorProvider, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { openContextMenu } from 'vs/workbench/contrib/terminal/browser/terminalContextMenu'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; -import { TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TERMINAL_CONFIG_SECTION, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; import { terminalStickyScrollHoverBackground } from 'vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry'; const enum OverlayState { @@ -327,28 +326,23 @@ export class TerminalStickyScrollOverlay extends Disposable { this._xterm.raw.element.parentElement.append(this._element); this._register(toDisposable(() => this._element?.remove())); - // Create command navigation keybinding hint if appropriate - const scrollToPreviousCommandKeybinding = this._keybindingService.lookupKeybinding('workbench.action.terminal.scrollToPreviousCommand'); + // Fill tooltip + let hoverTitle = localize('stickyScrollHoverTitle', 'Navigate to Command'); + const scrollToPreviousCommandKeybinding = this._keybindingService.lookupKeybinding(TerminalCommandId.ScrollToPreviousCommand); if (scrollToPreviousCommandKeybinding) { - const keybindingHint = $('.keybinding-hint'); - const localizedText = localize({ - key: 'command-navigation-hint', - comment: ['{0} is the localized keybinding to navigate commands'] - }, '{0} to navigate commands', '{0}'); - const localizedTextPrefix = localizedText.substring(0, localizedText.indexOf('{0}')); - const localizedTextSuffix = localizedText.substring(localizedText.indexOf('{0}') + 3); - const label = new KeybindingLabel(keybindingHint, OS); - label.set(scrollToPreviousCommandKeybinding); - // Insert and use a non-breaking space for boundaries to space out naturally - if (localizedTextPrefix) { - label.element.insertAdjacentText('beforebegin', localizedTextPrefix.replace(/ $/, '\u00A0')); + const label = scrollToPreviousCommandKeybinding.getLabel(); + if (label) { + hoverTitle += '\n' + localize('labelWithKeybinding', "{0} ({1})", terminalStrings.scrollToPreviousCommand.value, label); } - if (localizedTextSuffix) { - label.element.insertAdjacentText('afterend', localizedTextSuffix.replace(/^ /, '\u00A0')); - } - - hoverOverlay.append(keybindingHint); } + const scrollToNextCommandKeybinding = this._keybindingService.lookupKeybinding(TerminalCommandId.ScrollToNextCommand); + if (scrollToNextCommandKeybinding) { + const label = scrollToNextCommandKeybinding.getLabel(); + if (label) { + hoverTitle += '\n' + localize('labelWithKeybinding', "{0} ({1})", terminalStrings.scrollToNextCommand.value, label); + } + } + hoverOverlay.title = hoverTitle; const scrollBarWidth = (this._xterm.raw as any as { _core: IXtermCore })._core.viewport?.scrollBarWidth; if (scrollBarWidth !== undefined) {