Skip to content

Commit

Permalink
feat: add terminal group
Browse files Browse the repository at this point in the history
  • Loading branch information
CyanSalt committed Aug 15, 2022
1 parent 218914c commit b8a1268
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 32 deletions.
2 changes: 1 addition & 1 deletion addons/launcher/src/main/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function fillLauncherIDs(launchers: LauncherInfo[], old: Launcher[] | null) {
}
return {
...launcher,
id: matched ? matched.id : generateID(),
id: matched ? matched.id : `launcher@${generateID()}`,
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion addons/launcher/typings/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ export interface LauncherInfo {
}

export interface Launcher extends LauncherInfo {
id: number,
id: string,
}
1 change: 1 addition & 0 deletions addons/menu/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"Terminal#!menu.terminal": "终端",
"New Tab#!menu.newtab": "新建标签页",
"Duplicate Tab#!menu.duplicatetab": "复制标签页",
"Split Tab#!menu.splittab": "拆分标签页",
"New Window#!menu.newwindow": "新建窗口",
"Go Back#!menu.goback": "后退",
"Go Forward#!menu.goforward": "前进",
Expand Down
13 changes: 9 additions & 4 deletions resources/terminal.menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@
"accelerator": "CmdOrCtrl+T",
"command": "open-tab"
},
{
"label": "New Window#!menu.newwindow",
"accelerator": "CmdOrCtrl+N",
"command": "global:open-window"
},
{
"label": "Duplicate Tab#!menu.duplicatetab",
"accelerator": "CmdOrCtrl+Shift+D",
"accelerator": "CmdOrCtrl+D",
"command": "duplicate-tab"
},
{
"label": "New Window#!menu.newwindow",
"accelerator": "CmdOrCtrl+N",
"command": "global:open-window"
"label": "Split Tab#!menu.splittab",
"accelerator": "CmdOrCtrl+Shift+D",
"command": "split-tab"
},
{
"type": "separator"
Expand Down
18 changes: 14 additions & 4 deletions src/renderer/components/TabItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ const emit = defineEmits<{
const settings = useSettings()
const terminal = $(useCurrentTerminal())
const isFocused: boolean = $computed(() => {
return Boolean(tab) && terminal === tab
})
const isActive = $computed(() => {
if (isFocused) return true
return terminal?.group && tab?.group
&& terminal.group.type === tab.group.type
&& terminal.group.id === tab.group.id
})
const pane = $computed(() => {
if (!tab) return null
return tab.pane
Expand All @@ -34,7 +42,7 @@ const iconEntry = $computed(() => {
})
const title = $computed(() => {
if (group) return group.title
if (group?.title) return group.title
return tab ? getTerminalTabTitle(tab) : ''
})
Expand Down Expand Up @@ -65,7 +73,7 @@ function close() {
</script>

<template>
<div :class="['tab-item', { active: isFocused }]">
<div :class="['tab-item', { active: isActive, focused: isFocused }]">
<div class="tab-item-card">
<div class="tab-overview">
<div class="tab-title">
Expand Down Expand Up @@ -104,8 +112,7 @@ function close() {
min-width: 0;
opacity: 0.5;
transition: opacity 0.2s;
// .tab-item:hover &,
.tab-item.active &,
.tab-item.focused &,
.sortable-item.dragging & {
opacity: 1;
}
Expand All @@ -132,6 +139,9 @@ function close() {
padding: 0 8px;
border-radius: 8px;
.tab-item.active & {
background: linear-gradient(to right, transparent, var(--design-card-background));
}
.tab-item.focused & {
background: var(--design-card-background);
}
}
Expand Down
26 changes: 21 additions & 5 deletions src/renderer/components/TabList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import * as path from 'path'
import * as commas from '../../../api/core-renderer'
import { useAsyncComputed } from '../../shared/compositions'
import {
useTerminalTabs,
createTerminalTab,
moveTerminalTab,
activateTerminalTab,
createTerminalTab,
getTerminalTabIndex,
moveTerminalTab,
splitTerminalTab,
useCurrentTerminal,
useTerminalTabs,
} from '../compositions/terminal'
import { openContextMenu } from '../utils/frame'
import { handleMousePressing } from '../utils/helper'
Expand All @@ -19,11 +21,15 @@ const lists = commas.proxy.context.getCollection('terminal.ui-side-list')
const shells = $(useAsyncComputed(() => getShells(), []))
const tabs = $(useTerminalTabs())
const terminal = $(useCurrentTerminal())
let width = $ref(176)
const standaloneTabs = $computed(() => {
return tabs.filter(tab => !tab.group)
return tabs.filter(tab => {
if (!tab.group) return true
return tab.group.type === 'default'
})
})
function sortTabs(from: number, to: number) {
Expand All @@ -40,6 +46,16 @@ function selectShell(event: MouseEvent) {
})), event)
}
function selectDefaultShell(event: MouseEvent) {
if (process.platform === 'darwin' ? event.metaKey : event.ctrlKey) {
if (terminal) {
splitTerminalTab(terminal)
}
} else {
createTerminalTab()
}
}
function resize(startingEvent: DragEvent) {
const original = width
const start = startingEvent.clientX
Expand Down Expand Up @@ -74,7 +90,7 @@ function resize(startingEvent: DragEvent) {
</div>
<div
class="default-shell anchor"
@click="createTerminalTab()"
@click="selectDefaultShell"
@contextmenu="selectShell"
>
<span class="feather-icon icon-plus"></span>
Expand Down
49 changes: 49 additions & 0 deletions src/renderer/components/TerminalGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script lang="ts" setup>
import 'xterm/css/xterm.css'
import type { TerminalTab } from '../../typings/terminal'
import { activateTerminalTab, useTerminalTabs } from '../compositions/terminal'
import { getTerminalTabID } from '../utils/terminal'
import TerminalTeletype from './TerminalTeletype.vue'
const { tab } = defineProps<{
tab: TerminalTab,
}>()
const tabs = $(useTerminalTabs())
const groupTabs = $computed(() => {
const group = tab.group
if (!group) return [tab]
return tabs.filter(item => {
if (!item.group) return false
return item.group.type === group.type
&& item.group.id === group.id
})
})
function activate(item: TerminalTab) {
activateTerminalTab(item)
}
</script>

<template>
<article class="terminal-group">
<TerminalTeletype
v-for="item in groupTabs"
:key="getTerminalTabID(item)"
:tab="item"
@click="activate(item)"
/>
</article>
</template>

<style lang="scss" scoped>
@use '../assets/_partials';
.terminal-group {
position: relative;
display: flex;
flex: 1;
min-height: 0;
}
</style>
14 changes: 7 additions & 7 deletions src/renderer/components/TerminalTeletype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { tab } = defineProps<{
tab: TerminalTab,
}>()
const terminal = $ref<HTMLElement | undefined>()
const element = $ref<HTMLElement | undefined>()
function dragFileOver(event: DragEvent) {
if (event.dataTransfer) {
Expand Down Expand Up @@ -63,7 +63,7 @@ function fit() {
const observer = new ResizeObserver(fit)
watchEffect((onInvalidate) => {
const el = terminal
const el = element
if (!el) return
const xterm = tab.xterm
xterm.open(el)
Expand All @@ -80,19 +80,18 @@ onActivated(() => {
if (xterm['_core'].viewport) {
xterm['_core'].viewport.syncScrollArea(true)
}
xterm.focus()
})
</script>

<template>
<article
<div
class="terminal-teletype"
@contextmenu="openEditingMenu"
@dragover.prevent="dragFileOver"
@drop.prevent="dropFile"
>
<div ref="terminal" class="terminal-content"></div>
</article>
<div ref="element" class="terminal-content"></div>
</div>
</template>

<style lang="scss" scoped>
Expand All @@ -102,11 +101,12 @@ onActivated(() => {
position: relative;
display: flex;
flex: 1;
min-height: 0;
min-width: 0;
}
.terminal-content {
flex: 1;
min-width: 0;
overflow: hidden;
:deep(.xterm) {
padding: 4px 12px;
}
Expand Down
7 changes: 5 additions & 2 deletions src/renderer/components/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import ActionBar from './ActionBar.vue'
import CodeEditorPane from './CodeEditorPane.vue'
import FindBox from './FindBox.vue'
import TabList from './TabList.vue'
import TerminalTeletype from './TerminalTeletype.vue'
import TerminalGroup from './TerminalGroup.vue'
import TitleBar from './TitleBar.vue'
import '../assets/fonts/devicon.css'
import '../assets/fonts/feather.css'
Expand All @@ -48,12 +48,15 @@ const TerminalComponent = $computed(() => {
return terminal.pane.component
}
} else {
return TerminalTeletype
return TerminalGroup
}
})
const tabId = $computed(() => {
if (!terminal) return ''
if (terminal.group) {
return terminal.group.id
}
return getTerminalTabID(terminal)
})
Expand Down
34 changes: 31 additions & 3 deletions src/renderer/compositions/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as os from 'os'
import * as path from 'path'
import { ipcRenderer, shell } from 'electron'
import { isMatch, trim } from 'lodash'
import { markRaw, reactive, shallowReactive, toRaw, watch, watchEffect } from 'vue'
import { markRaw, nextTick, reactive, shallowReactive, toRaw, watch, watchEffect } from 'vue'
import { Terminal } from 'xterm'
import type { ITerminalOptions } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
Expand Down Expand Up @@ -183,7 +183,7 @@ export function getTerminalTabTitle(tab: TerminalTab) {
if (tab.pane && !tab.shell) {
return translate(tab.pane.title)
}
if (tab.group) {
if (tab.group?.title) {
return tab.group.title
}
if (process.platform !== 'win32' && tab.title) {
Expand Down Expand Up @@ -228,7 +228,7 @@ export function openCodeEditorTab(file: string) {
}

function handleTerminalTabHistory() {
let navigating: number | null = null
let navigating: string | null = null
window.addEventListener('popstate', event => {
if (!event.state) return
const targetIndex = tabs.findIndex(item => getTerminalTabID(item) === event.state.id)
Expand Down Expand Up @@ -256,6 +256,12 @@ export function handleTerminalMessages() {
watch($$(currentTerminal), () => {
paneTabURL = ''
}, { flush: 'sync' })
watch($$(currentTerminal), async tab => {
await nextTick()
if (tab && !tab.pane) {
tab.xterm.focus()
}
})
ipcRenderer.on('open-tab', (event, options: CreateTerminalTabOptions) => {
createTerminalTab(options)
})
Expand All @@ -267,6 +273,11 @@ export function handleTerminalMessages() {
})
}
})
ipcRenderer.on('split-tab', () => {
if (currentTerminal) {
splitTerminalTab(currentTerminal)
}
})
ipcRenderer.on('close-tab', () => {
if (currentTerminal) {
closeTerminalTab(currentTerminal)
Expand Down Expand Up @@ -491,3 +502,20 @@ export function moveTerminalTab(tab: TerminalTab, index: number) {
activeIndex += 1
}
}

export function splitTerminalTab(tab: TerminalTab) {
if (tab.pane) {
return tab
}
if (!tab.group) {
tab.group = {
type: 'default',
id: getTerminalTabID(tab),
}
}
return createTerminalTab({
cwd: tab.cwd,
shell: tab.shell,
group: tab.group,
})
}
6 changes: 3 additions & 3 deletions src/renderer/utils/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ export function getWindowsProcessInfo(shell: string, title: string): Partial<Ter
export function getTerminalTabID(tab: TerminalTab) {
if (tab.pane) {
if (tab.pane.type === 'editor') {
return tab.shell
return `editor@${tab.shell}`
} else {
return tab.process
return `pane@${tab.process}`
}
} else {
return tab.pid
return `process@${tab.pid}`
}
}
4 changes: 2 additions & 2 deletions src/typings/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export interface TerminalTabPane {

export interface TerminalTabGroup {
type: string,
id: number,
title: string,
id: string,
title?: string,
icon?: IconEntry,
}

Expand Down

0 comments on commit b8a1268

Please sign in to comment.