feat: 补全终端交互逻辑.
This commit is contained in:
@@ -32,7 +32,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
CONNECT("co",
|
CONNECT("co",
|
||||||
TerminalConnectHandler.class,
|
TerminalConnectHandler.class,
|
||||||
new String[]{"type", "sessionId", "cols", "rows"},
|
new String[]{"type", "sessionId", "terminalType", "cols", "rows"},
|
||||||
TerminalConnectRequest.class),
|
TerminalConnectRequest.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
|
|||||||
// 建立连接
|
// 建立连接
|
||||||
SessionStore sessionStore = hostTerminalService.openSessionStore(connect);
|
SessionStore sessionStore = hostTerminalService.openSessionStore(connect);
|
||||||
terminalSession = new TerminalSession(sessionId, channel, sessionStore, config);
|
terminalSession = new TerminalSession(sessionId, channel, sessionStore, config);
|
||||||
terminalSession.connect(body.getCols(), body.getRows());
|
terminalSession.connect(body.getTerminalType(), body.getCols(), body.getRows());
|
||||||
log.info("TerminalConnectHandler-handle success sessionId: {}", sessionId);
|
log.info("TerminalConnectHandler-handle success sessionId: {}", sessionId);
|
||||||
return terminalSession;
|
return terminalSession;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@Schema(name = "TerminalConnectRequest", description = "终端连接请求 实体对象")
|
@Schema(name = "TerminalConnectRequest", description = "终端连接请求 实体对象")
|
||||||
public class TerminalConnectRequest extends TerminalBasePayload {
|
public class TerminalConnectRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "伪终端类型")
|
||||||
|
private String terminalType;
|
||||||
|
|
||||||
@Schema(description = "列数")
|
@Schema(description = "列数")
|
||||||
private Integer cols;
|
private Integer cols;
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ public interface ITerminalSession extends SafeCloseable {
|
|||||||
/**
|
/**
|
||||||
* 连接
|
* 连接
|
||||||
*
|
*
|
||||||
|
* @param terminalType terminalType
|
||||||
* @param cols cols
|
* @param cols cols
|
||||||
* @param rows rows
|
* @param rows rows
|
||||||
*/
|
*/
|
||||||
void connect(int cols, int rows);
|
void connect(String terminalType, int cols, int rows);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置大小
|
* 重置大小
|
||||||
|
|||||||
@@ -61,14 +61,13 @@ public class TerminalSession implements ITerminalSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connect(int cols, int rows) {
|
public void connect(String terminalType, int cols, int rows) {
|
||||||
config.setCols(cols);
|
config.setCols(cols);
|
||||||
config.setRows(rows);
|
config.setRows(rows);
|
||||||
// 打开 shell
|
// 打开 shell
|
||||||
this.executor = sessionStore.getShellExecutor();
|
this.executor = sessionStore.getShellExecutor();
|
||||||
executor.size(cols, rows);
|
executor.size(cols, rows);
|
||||||
// FIXME
|
executor.terminalType(terminalType);
|
||||||
executor.terminalType(TerminalType.XTERM.getType());
|
|
||||||
executor.streamHandler(this::streamHandler);
|
executor.streamHandler(this::streamHandler);
|
||||||
executor.callback(this::eofCallback);
|
executor.callback(this::eofCallback);
|
||||||
executor.connect();
|
executor.connect();
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class TerminalPreferenceModel implements PreferenceModel {
|
|||||||
@Schema(description = "右键选中词条")
|
@Schema(description = "右键选中词条")
|
||||||
private Boolean rightClickSelectsWord;
|
private Boolean rightClickSelectsWord;
|
||||||
|
|
||||||
@Schema(description = "选中词条自动复制")
|
@Schema(description = "选中自动复制")
|
||||||
private Boolean selectionChangeCopy;
|
private Boolean selectionChangeCopy;
|
||||||
|
|
||||||
@Schema(description = "复制去除空格")
|
@Schema(description = "复制去除空格")
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { Message } from '@arco-design/web-vue';
|
|||||||
export default function useCopy() {
|
export default function useCopy() {
|
||||||
const { copy: c } = useClipboard();
|
const { copy: c } = useClipboard();
|
||||||
// 复制
|
// 复制
|
||||||
const copy = async (value: string | undefined, tips = `${value} 已复制`) => {
|
const copy = async (value: string | undefined, tips: string | boolean = `${value} 已复制`) => {
|
||||||
try {
|
try {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await c(value);
|
await c(value);
|
||||||
if (tips) {
|
if (tips) {
|
||||||
Message.success(tips);
|
Message.success(tips as string);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Message.error('复制失败');
|
Message.error('复制失败');
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -64,6 +63,7 @@
|
|||||||
:deep(.arco-input-wrapper) {
|
:deep(.arco-input-wrapper) {
|
||||||
background-color: var(--color-fill-3)
|
background-color: var(--color-fill-3)
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.arco-select) {
|
:deep(.arco-select) {
|
||||||
background-color: var(--color-fill-3)
|
background-color: var(--color-fill-3)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@
|
|||||||
</a-row>
|
</a-row>
|
||||||
<a-row class="mb16" align="stretch" :gutter="16">
|
<a-row class="mb16" align="stretch" :gutter="16">
|
||||||
<!-- 右键选中词条 -->
|
<!-- 右键选中词条 -->
|
||||||
<block-setting-item label="右键选中词条" desc="右键文本">
|
<block-setting-item label="右键选中词条" desc="右键文本后会根据单词分隔符自动选中词条">
|
||||||
<a-switch type="round"
|
<a-switch type="round"
|
||||||
v-model="formModel.rightClickSelectsWord" />
|
v-model="formModel.rightClickSelectsWord" />
|
||||||
</block-setting-item>
|
</block-setting-item>
|
||||||
<!-- 选中词条自动复制 -->
|
<!-- 选中自动复制 -->
|
||||||
<block-setting-item label="选中词条自动复制" desc="自动将选中的词条复制到剪切板">
|
<block-setting-item label="选中自动复制" desc="自动将选中的文本复制到剪切板">
|
||||||
<a-switch type="round"
|
<a-switch type="round"
|
||||||
v-model="formModel.selectionChangeCopy" />
|
v-model="formModel.selectionChangeCopy" />
|
||||||
</block-setting-item>
|
</block-setting-item>
|
||||||
@@ -41,14 +41,14 @@
|
|||||||
v-model="formModel.copyAutoTrim" />
|
v-model="formModel.copyAutoTrim" />
|
||||||
</block-setting-item>
|
</block-setting-item>
|
||||||
<!-- 粘贴去除空格 -->
|
<!-- 粘贴去除空格 -->
|
||||||
<block-setting-item label="粘贴去除空格" desc="粘贴文本前自动删除尾部空格">
|
<block-setting-item label="粘贴去除空格" desc="粘贴文本前自动删除尾部空格 如: 命令输入框, 命令编辑器, 右键粘贴, 粘贴按钮, 右键菜单粘贴, 自定义粘贴快捷键. (系统快捷键无法干预 如: ctrl + shift + v, shift + insert)">
|
||||||
<a-switch type="round"
|
<a-switch type="round"
|
||||||
v-model="formModel.pasteAutoTrim" />
|
v-model="formModel.pasteAutoTrim" />
|
||||||
</block-setting-item>
|
</block-setting-item>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row class="mb16" align="stretch" :gutter="16">
|
<a-row class="mb16" align="stretch" :gutter="16">
|
||||||
<!-- 右键粘贴 -->
|
<!-- 右键粘贴 -->
|
||||||
<block-setting-item label="右键粘贴" desc="右键自动粘贴, 启用后需要关闭右键菜单">
|
<block-setting-item label="右键粘贴" desc="右键自动粘贴, 启用后需要关闭右键菜单 (若开启了右键选中词条, 有选中的文本时, 右键粘贴无效)">
|
||||||
<a-switch type="round"
|
<a-switch type="round"
|
||||||
v-model="formModel.rightClickPaste" />
|
v-model="formModel.rightClickPaste" />
|
||||||
</block-setting-item>
|
</block-setting-item>
|
||||||
|
|||||||
@@ -83,8 +83,9 @@
|
|||||||
const session = ref<ITerminalSession>();
|
const session = ref<ITerminalSession>();
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
// 右键菜单补充
|
|
||||||
// 搜索 search color 配置
|
// 搜索 search color 配置
|
||||||
|
// 右键菜单补充 启用右键菜单 enableRightClickMenu 粘贴逻辑
|
||||||
|
// 快捷键补充 粘贴逻辑
|
||||||
// 截屏
|
// 截屏
|
||||||
// 主机获取逻辑 最近连接逻辑
|
// 主机获取逻辑 最近连接逻辑
|
||||||
|
|
||||||
@@ -100,7 +101,7 @@
|
|||||||
// 发送命令
|
// 发送命令
|
||||||
const writeCommand = (value: string) => {
|
const writeCommand = (value: string) => {
|
||||||
if (session.value?.canWrite) {
|
if (session.value?.canWrite) {
|
||||||
session.value.paste(value);
|
session.value.pasteTrimEnd(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -129,9 +130,9 @@
|
|||||||
// 全选
|
// 全选
|
||||||
checkAll: () => session.value?.selectAll(),
|
checkAll: () => session.value?.selectAll(),
|
||||||
// 复制选中部分
|
// 复制选中部分
|
||||||
copy: () => copy(session.value?.getSelection(), '已复制'),
|
copy: () => session.value?.copySelection(),
|
||||||
// 粘贴
|
// 粘贴
|
||||||
paste: async () => session.value?.paste(await readText()),
|
paste: async () => session.value?.pasteTrimEnd(await readText()),
|
||||||
// ctrl + c
|
// ctrl + c
|
||||||
interrupt: () => session.value?.paste(String.fromCharCode(3)),
|
interrupt: () => session.value?.paste(String.fromCharCode(3)),
|
||||||
// 回车
|
// 回车
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import {
|
import { ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
|
||||||
ITerminalChannel,
|
|
||||||
ITerminalOutputProcessor,
|
|
||||||
ITerminalSessionManager,
|
|
||||||
OutputPayload
|
|
||||||
} from '../types/terminal.type';
|
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
import { TerminalStatus } from '../types/terminal.const';
|
import { TerminalStatus } from '../types/terminal.const';
|
||||||
|
import { useTerminalStore } from '@/store';
|
||||||
|
|
||||||
// 终端输出消息体处理器实现
|
// 终端输出消息体处理器实现
|
||||||
export default class TerminalOutputProcessor implements ITerminalOutputProcessor {
|
export default class TerminalOutputProcessor implements ITerminalOutputProcessor {
|
||||||
@@ -29,8 +25,14 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
session.status = TerminalStatus.CLOSED;
|
session.status = TerminalStatus.CLOSED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { preference } = useTerminalStore();
|
||||||
// 发送 connect 命令
|
// 发送 connect 命令
|
||||||
this.channel.send(InputProtocol.CONNECT, { sessionId, cols: session.inst.cols, rows: session.inst.rows });
|
this.channel.send(InputProtocol.CONNECT, {
|
||||||
|
sessionId,
|
||||||
|
terminalType: preference.sessionSetting.terminalEmulationType || 'xterm',
|
||||||
|
cols: session.inst.cols,
|
||||||
|
rows: session.inst.rows
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理连接消息
|
// 处理连接消息
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
|
import type { UnwrapRef } from 'vue';
|
||||||
|
import type { TerminalPreference } from '@/store/modules/terminal/types';
|
||||||
import type { ITerminalChannel, ITerminalSession, TerminalAddons } from '../types/terminal.type';
|
import type { ITerminalChannel, ITerminalSession, TerminalAddons } from '../types/terminal.type';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
import { fontFamilySuffix, TerminalStatus } from '../types/terminal.const';
|
import { fontFamilySuffix, TerminalStatus } from '../types/terminal.const';
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
import { ITerminalOptions, Terminal } from 'xterm';
|
import { ITerminalOptions, Terminal } from 'xterm';
|
||||||
import { FitAddon } from 'xterm-addon-fit';
|
import { FitAddon } from 'xterm-addon-fit';
|
||||||
import { WebglAddon } from 'xterm-addon-webgl';
|
|
||||||
import { WebLinksAddon } from 'xterm-addon-web-links';
|
import { WebLinksAddon } from 'xterm-addon-web-links';
|
||||||
import { SearchAddon } from 'xterm-addon-search';
|
import { SearchAddon } from 'xterm-addon-search';
|
||||||
import { ImageAddon } from 'xterm-addon-image';
|
import { ImageAddon } from 'xterm-addon-image';
|
||||||
import { CanvasAddon } from 'xterm-addon-canvas';
|
import { CanvasAddon } from 'xterm-addon-canvas';
|
||||||
|
import { WebglAddon } from 'xterm-addon-webgl';
|
||||||
|
import { playBell } from '@/utils/bell';
|
||||||
|
import useCopy from '@/hooks/copy';
|
||||||
|
|
||||||
|
const copy = useCopy();
|
||||||
|
|
||||||
// 终端会话实现
|
// 终端会话实现
|
||||||
export default class TerminalSession implements ITerminalSession {
|
export default class TerminalSession implements ITerminalSession {
|
||||||
@@ -49,33 +55,29 @@ export default class TerminalSession implements ITerminalSession {
|
|||||||
this.inst = new Terminal({
|
this.inst = new Terminal({
|
||||||
...(preference.displaySetting as any),
|
...(preference.displaySetting as any),
|
||||||
theme: preference.theme.schema,
|
theme: preference.theme.schema,
|
||||||
fastScrollModifier: 'alt',
|
fastScrollModifier: !!preference.interactSetting.fastScrollModifier ? 'alt' : 'none',
|
||||||
|
altClickMovesCursor: !!preference.interactSetting.altClickMovesCursor,
|
||||||
|
rightClickSelectsWord: !!preference.interactSetting.rightClickSelectsWord,
|
||||||
fontFamily: preference.displaySetting.fontFamily + fontFamilySuffix,
|
fontFamily: preference.displaySetting.fontFamily + fontFamilySuffix,
|
||||||
|
wordSeparator: preference.interactSetting.wordSeparator,
|
||||||
|
scrollback: preference.sessionSetting.scrollBackLine,
|
||||||
});
|
});
|
||||||
|
// 注册快捷键
|
||||||
|
// 注册事件
|
||||||
|
this.registerEvent(dom, preference);
|
||||||
// 注册插件
|
// 注册插件
|
||||||
this.addons.fit = new FitAddon();
|
this.registerAddions(preference);
|
||||||
// this.addons.webgl = new WebglAddon();
|
|
||||||
this.addons.canvas = new CanvasAddon();
|
|
||||||
this.addons.link = new WebLinksAddon();
|
|
||||||
this.addons.search = new SearchAddon();
|
|
||||||
this.addons.image = new ImageAddon();
|
|
||||||
for (const addon of Object.values(this.addons)) {
|
|
||||||
this.inst.loadAddon(addon);
|
|
||||||
}
|
|
||||||
// 打开终端
|
// 打开终端
|
||||||
this.inst.open(dom);
|
this.inst.open(dom);
|
||||||
// 自适应
|
// 自适应
|
||||||
this.addons.fit.fit();
|
this.addons.fit.fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置已连接
|
// 注册事件
|
||||||
connect(): void {
|
private registerEvent(dom: HTMLElement, preference: UnwrapRef<TerminalPreference>) {
|
||||||
this.status = TerminalStatus.CONNECTED;
|
|
||||||
this.connected = true;
|
|
||||||
this.inst.focus();
|
|
||||||
// 注册输入事件
|
// 注册输入事件
|
||||||
this.inst.onData(s => {
|
this.inst.onData(s => {
|
||||||
if (!this.canWrite) {
|
if (!this.canWrite || !this.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 输入
|
// 输入
|
||||||
@@ -84,14 +86,81 @@ export default class TerminalSession implements ITerminalSession {
|
|||||||
command: s
|
command: s
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// 启用响铃
|
||||||
|
if (preference.interactSetting.enableBell) {
|
||||||
|
this.inst.onBell(() => {
|
||||||
|
// 播放蜂鸣
|
||||||
|
playBell();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 选中复制
|
||||||
|
if (preference.interactSetting.selectionChangeCopy) {
|
||||||
|
this.inst.onSelectionChange(() => {
|
||||||
|
// 复制选中内容
|
||||||
|
this.copySelection();
|
||||||
|
});
|
||||||
|
}
|
||||||
// 注册 resize 事件
|
// 注册 resize 事件
|
||||||
this.inst.onResize(({ cols, rows }) => {
|
this.inst.onResize(({ cols, rows }) => {
|
||||||
|
if (!this.connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.channel.send(InputProtocol.RESIZE, {
|
this.channel.send(InputProtocol.RESIZE, {
|
||||||
sessionId: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
cols,
|
cols,
|
||||||
rows
|
rows
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// 设置右键选项
|
||||||
|
dom.addEventListener('contextmenu', async (event) => {
|
||||||
|
// 如果开启了右键粘贴 右键选中 右键菜单 则关闭默认右键菜单
|
||||||
|
if (preference.interactSetting.rightClickSelectsWord
|
||||||
|
|| preference.interactSetting.rightClickPaste
|
||||||
|
|| preference.interactSetting.enableRightClickMenu) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
// 右键粘贴逻辑
|
||||||
|
if (preference.interactSetting.rightClickPaste) {
|
||||||
|
if (!this.canWrite || !this.connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 未开启右键选中 || 开启并无选中的内容则粘贴
|
||||||
|
if (!preference.interactSetting.rightClickSelectsWord || !this.inst.hasSelection()) {
|
||||||
|
this.pasteTrimEnd(await copy.readText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册插件
|
||||||
|
private registerAddions(preference: UnwrapRef<TerminalPreference>) {
|
||||||
|
this.addons.fit = new FitAddon();
|
||||||
|
this.addons.search = new SearchAddon();
|
||||||
|
// 超链接插件
|
||||||
|
if (preference.pluginsSetting.enableWeblinkPlugin) {
|
||||||
|
this.addons.weblink = new WebLinksAddon();
|
||||||
|
}
|
||||||
|
if (preference.pluginsSetting.enableWebglPlugin) {
|
||||||
|
// WebGL 渲染插件
|
||||||
|
this.addons.webgl = new WebglAddon();
|
||||||
|
} else {
|
||||||
|
// canvas 渲染插件
|
||||||
|
this.addons.canvas = new CanvasAddon();
|
||||||
|
}
|
||||||
|
// 图片渲染插件
|
||||||
|
if (preference.pluginsSetting.enableImagePlugin) {
|
||||||
|
this.addons.image = new ImageAddon();
|
||||||
|
}
|
||||||
|
for (const addon of Object.values(this.addons)) {
|
||||||
|
this.inst.loadAddon(addon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置已连接
|
||||||
|
connect(): void {
|
||||||
|
this.status = TerminalStatus.CONNECTED;
|
||||||
|
this.connected = true;
|
||||||
|
this.inst.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置是否可写
|
// 设置是否可写
|
||||||
@@ -132,15 +201,36 @@ export default class TerminalSession implements ITerminalSession {
|
|||||||
this.inst.focus();
|
this.inst.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 粘贴并且去除尾部空格 (如果配置)
|
||||||
|
pasteTrimEnd(value: string): void {
|
||||||
|
if (useTerminalStore().preference.interactSetting.pasteAutoTrim) {
|
||||||
|
// 粘贴前去除尾部空格
|
||||||
|
this.inst.paste(value.trimEnd());
|
||||||
|
} else {
|
||||||
|
this.inst.paste(value);
|
||||||
|
}
|
||||||
|
this.inst.focus();
|
||||||
|
}
|
||||||
|
|
||||||
// 选中全部
|
// 选中全部
|
||||||
selectAll(): void {
|
selectAll(): void {
|
||||||
this.inst.selectAll();
|
this.inst.selectAll();
|
||||||
this.inst.focus();
|
this.inst.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取选中
|
// 复制选中
|
||||||
getSelection(): string {
|
copySelection(): string {
|
||||||
const selection = this.inst.getSelection();
|
let selection = this.inst.getSelection();
|
||||||
|
if (selection) {
|
||||||
|
// 去除尾部空格
|
||||||
|
const { preference } = useTerminalStore();
|
||||||
|
if (preference.interactSetting.copyAutoTrim) {
|
||||||
|
selection = selection.trimEnd();
|
||||||
|
}
|
||||||
|
// 复制
|
||||||
|
copy.copy(selection, false);
|
||||||
|
}
|
||||||
|
// 聚焦
|
||||||
this.inst.focus();
|
this.inst.focus();
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const InputProtocol = {
|
|||||||
// 连接主机
|
// 连接主机
|
||||||
CONNECT: {
|
CONNECT: {
|
||||||
type: 'co',
|
type: 'co',
|
||||||
template: ['type', 'sessionId', 'cols', 'rows']
|
template: ['type', 'sessionId', 'terminalType', 'cols', 'rows']
|
||||||
},
|
},
|
||||||
// 关闭连接
|
// 关闭连接
|
||||||
CLOSE: {
|
CLOSE: {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ export interface TerminalAddons {
|
|||||||
fit: FitAddon;
|
fit: FitAddon;
|
||||||
webgl: WebglAddon;
|
webgl: WebglAddon;
|
||||||
canvas: CanvasAddon;
|
canvas: CanvasAddon;
|
||||||
link: WebLinksAddon;
|
weblink: WebLinksAddon;
|
||||||
search: SearchAddon;
|
search: SearchAddon;
|
||||||
image: ImageAddon;
|
image: ImageAddon;
|
||||||
}
|
}
|
||||||
@@ -152,10 +152,12 @@ export interface ITerminalSession {
|
|||||||
clear: () => void;
|
clear: () => void;
|
||||||
// 粘贴
|
// 粘贴
|
||||||
paste: (value: string) => void;
|
paste: (value: string) => void;
|
||||||
|
// 粘贴并且去除尾部空格 (如果配置)
|
||||||
|
pasteTrimEnd: (value: string) => void;
|
||||||
// 选中全部
|
// 选中全部
|
||||||
selectAll: () => void;
|
selectAll: () => void;
|
||||||
// 获取选中
|
// 复制选中
|
||||||
getSelection: () => string;
|
copySelection: () => string;
|
||||||
// 去顶部
|
// 去顶部
|
||||||
toTop: () => void;
|
toTop: () => void;
|
||||||
// 去底部
|
// 去底部
|
||||||
|
|||||||
Reference in New Issue
Block a user