编写自己的终端模拟器

  • 一个简单的终端
  • 更多功能
  • 颜色
  • 其他设置
  • 更新窗口标题
  • 写在最后

原文链接:
https://vincent.bernat.ch/en/blog/2017-write-own-terminal
作者:
文森特·伯纳特 2017 年 2 月 7 日
译者:
whstudio123
源代码位置:
https://github.com/vincentbernat/vbeterm

在我得到一台带有HiDPI显示器的笔记本电脑之前,我一直是rxvt-unicode的快乐用户。从LoDPI切换到HiDPI屏幕再切换回来很痛苦:我不得不手动调整所有终端上的字体大小或重新启动它们。

VTE是一个使用 GTK+ 工具包构建终端仿真器的库,用于处理 DPI 更改。许多终端仿真器都使用它,例如GNOME Terminal、evilvte、sakura、termit和ROXTerm。该库非常简单,如果您不需要很多功能,编写终端不会花费太多时间。

让我们看看如何写一个简单的。

一个简单的终端

让我们从具有默认设置的终端开始。我们将在 C 中编写它。另一个受支持的选项是Vala。

#include <vte/vte.h>static void
child_ready(VteTerminal *terminal, GPid pid, GError *error, gpointer user_data)
{if (!terminal) return;if (pid == -1) gtk_main_quit();
}int main(int argc, char *argv[])
{GtkWidget *window, *terminal;/* Initialise GTK, the window and the terminal */gtk_init(&argc, &argv);terminal = vte_terminal_new();window = gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window), "myterm");/* Start a new shell */gchar **envp = g_get_environ();gchar **command = (gchar *[]){g_strdup(g_environ_getenv(envp, "SHELL")), NULL };g_strfreev(envp);vte_terminal_spawn_async(VTE_TERMINAL(terminal),VTE_PTY_DEFAULT,NULL,         /* working directory  */command,      /* command */NULL,         /* environment */0,            /* spawn flags */NULL, NULL,   /* child setup */NULL,         /* child pid */-1,           /* timeout */NULL,         /* cancellable */child_ready,  /* callback */NULL);        /* user_data *//* Connect some signals */g_signal_connect(window, "delete-event", gtk_main_quit, NULL);g_signal_connect(terminal, "child-exited", gtk_main_quit, NULL);/* Put widgets together and run the main loop */gtk_container_add(GTK_CONTAINER(window), terminal);gtk_widget_show_all(window);gtk_main();
}

您可以使用以下命令编译它:

gcc -O2 -Wall $( pkg-config --cflags vte-2.91 ) term.c -o term $( pkg-config --libs vte-2.91 )

并运行它

./term

上图:简单的基于 VTE 的终端

更多功能

从这里,您可以查看文档以更改行为或添加更多功能。这里有三个例子。

颜色

您可以使用以下代码定义 16 种基本颜色:

#define CLR_R(x)   (((x) & 0xff0000) >> 16)
#define CLR_G(x)   (((x) & 0x00ff00) >>  8)
#define CLR_B(x)   (((x) & 0x0000ff) >>  0)
#define CLR_16(x)  ((double)(x) / 0xff)
#define CLR_GDK(x) (const GdkRGBA){ .red = CLR_16(CLR_R(x)), \.green = CLR_16(CLR_G(x)), \.blue = CLR_16(CLR_B(x)), \.alpha = 0 }
vte_terminal_set_colors(VTE_TERMINAL(terminal),&CLR_GDK(0xffffff),&(GdkRGBA){ .alpha = 0.85 },(const GdkRGBA[]){CLR_GDK(0x111111),CLR_GDK(0xd36265),CLR_GDK(0xaece91),CLR_GDK(0xe7e18c),CLR_GDK(0x5297cf),CLR_GDK(0x963c59),CLR_GDK(0x5E7175),CLR_GDK(0xbebebe),CLR_GDK(0x666666),CLR_GDK(0xef8171),CLR_GDK(0xcfefb3),CLR_GDK(0xfff796),CLR_GDK(0x74b8ef),CLR_GDK(0xb85e7b),CLR_GDK(0xA3BABF),CLR_GDK(0xffffff)
}, 16);

虽然您在屏幕截图上看不到它,但这也启用了背景透明度。
(透明度由合成器(在我的例子中是Compton )处理。)

其他设置

VTE带有许多设置来改变终端的行为。考虑以下代码:

vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), 0);
vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), FALSE);
vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE);
vte_terminal_set_mouse_autohide(VTE_TERMINAL(terminal), TRUE);

这会:

禁用回滚缓冲区;
在新输出上不滚动到底部;
击键时滚动到底部;
键入时隐藏鼠标光标。

更新窗口标题

应用程序可以使用XTerm 控制序列(例如,使用printf “\e]2;${title}\a”)更改窗口标题。如果你想让实际的窗口标题反映这一点,你需要定义这个函数:

static gboolean
on_title_changed(GtkWidget *terminal, gpointer user_data)
{GtkWindow *window = user_data;gtk_window_set_title(window,vte_terminal_get_window_title(VTE_TERMINAL(terminal))?:"Terminal");return TRUE;
}

然后,将其连接到适当的信号,在main():

g_signal_connect(terminal, "window-title-changed",G_CALLBACK(on_title_changed), GTK_WINDOW(window));

写在最后

我不需要做更多了,因为我在每个终端内都使用tmux 。在我自己的拷贝中,我还添加了使用当前窗口或其他窗口中的单词补全单词的功能(也称为动态缩写扩展)。这需要实现一个终端守护进程来用一个进程处理所有终端窗口,类似于urxvtcd.

虽然“从头开始”编写终端符合我的需要,但它可能不值得。evilvte是完全可定制的,并且可以是轻量级的。将其视为第一选择。老实说,我不记得为什么我没有选择它。

(对于“从头开始”的一些定义,因为艰苦的工作是由VTE处理的。 )

更新 (2017-02):evilvte自 2014 年以来没有看到更新。它的 GTK+3 支持是错误的。它不支持最新版本的 VTE 库。因此,使用它不是一个好主意。

您还应该注意,VTE的主要目标是成为一个支持GNOME 终端的库。值得注意的是,如果GNOME Terminal不需要某个功能,则不会将其添加到VTE中。如果它已经存在,它可能会被弃用和删除。

© 2017–2022 文森特·伯纳特

优秀网页翻译:编写自己的终端模拟器相关推荐

  1. 开源游戏机java模拟器_开源一个Flutter编写的完整终端模拟器

    上次开源了一个简易的终端模拟器,我也知道并不是标准的,但自己也一直在用,然后就发现了一些棘手的问题,就又跑去研究了一些完整终端的源码,termux,Android Terminal,最后成功的将他们的 ...

  2. 优秀网页翻译:高精度 10MHz GPS 驯服钟 (GPSDO) - Part3

    高精度 10MHz GPS 驯服钟 GPSDO - Part 3 Lars 代码的新版本,V3.60. 寻找最佳 TC 设置 设置 ADC 线性化参数 揭开谜底 新的 MDEV 和频率图 GPSDO ...

  3. 优秀网页翻译:Adafruit - 只读树莓派 - 关机时避免 SD 卡损坏

    只读树莓派 - 关机时避免 SD 卡损坏 概述 关注点 解决方案 在你开始之前 启用只读 /boot 使用"Lite"命令行操作系统 对彼此而言 恢复读/写访问 你还没有完成 原文 ...

  4. 优秀网页翻译:高精度 10MHz GPS 驯服钟 (GPSDO) - Part 2

    高精度 10MHz GPS 驯服驯服钟 GPSDO - Part 2 我学到的是 温度效应 DAC温度补偿 温度补偿结果 为什么 DAC 的温度补偿如此重要? GPS锁定丢失时的温度效应 Bliley ...

  5. 优秀网页翻译:高精度 10MHz GPS 驯服钟 (GPSDO) - Part 5

    高精度 10MHz GPS 驯服钟 GPSDO - Part 5 重大挫折! 回到绘图板 把事情分成两部分 GPSDO 的附加板 原型的初步结果 计数器/记录器版本 2 外壳 我犯了一个愚蠢的布局错误 ...

  6. 优秀网页翻译:一个智能旋钮:DIY haptic input knob: BLDC motor + round LCD

    一个智能旋钮:DIY haptic input knob: BLDC motor + round LCD 智能旋钮 硬件 设计 智能旋钮视图 演示视频 3D CAD 建立一个你自己的? 基础PCB 屏 ...

  7. 优秀网页翻译:高精度 10MHz GPS 驯服钟 (GPSDO) - Part 1

    高精度 10MHz GPS 驯服钟 GPSDO - Part 1 第一个原型 设计PCB 一些设计和布局决策 电源 电力调配 控制器电路 振荡电路 修整 OCXO 输出 微调增益设置 OCXO 电路 ...

  8. 优秀网页翻译:DS3231与 PCF2129 RTC比较

    RTC比较 实时时钟 DS3231 PCF2129 特性比较 精度比较 附加信息 相关文章 本文原文地址: https://blog.dan.drown.org/rtc-comparison/ 实时时 ...

  9. 优秀网页翻译:高精度 10MHz GPS 驯服钟 (GPSDO) - Part 4

    高精度 10MHz GPS 驯服钟 GPSDO - Part 4 监控.测量和记录 我的额外设计目标 摆脱困境 监控 GPSDO 状态报告 测量 GPSDO 10MHz 输出的精度 树莓派串口注意事项 ...

最新文章

  1. mybatis学习7 实战项目
  2. 11月16日bd之旅意外参加黄波博士讲座
  3. JZOJ 5439. 【NOIP2017提高A组集训10.31】Calculate
  4. 开始一个django项目
  5. python修饰符用法_c#教程之C#语言中的修饰符汇总
  6. uva297(quadtree)
  7. javascript 函数传参
  8. 安信可nbiot模块_安信可wifi模组特征
  9. 一元二次方程的解c语言,一元二次方程求解程序完整代码
  10. java计算1900到2015共有多少天?
  11. TypeWriter: Neural Type Prediction with Search-based Validation基于搜索的神经网络预测器
  12. PyCharm中的问题记录:failed to sync ide settings. click to sync
  13. [转] 如何用BSP树生成游戏地图
  14. 南京配眼镜避坑指南,轻松找到高性价比眼镜店
  15. 『Linux』Ubuntu Beaver(18.04) 配置 美化流程
  16. 谷歌浏览器突然不能翻译成中文
  17. php7.1.6验证码错误,steam输入验证码不正确怎么办
  18. Linux系统中最好用的截图软件介绍
  19. Python 用pyinstaller打包python程序,生成的exe文件过大问题
  20. Java零基础学习Day01(搭配视频)

热门文章

  1. VUE 实现拖拽效果
  2. 哈工大“科研神器”被禁,中国量子计算等高科技研发会受到什么影响?
  3. mysql如何两个表取差集_mysql 查询两张表的差集
  4. spring框架教程 Spring开发实例 spring mvc视频教程下载
  5. 【钱要花到刀刃上,该省省,该花花】你真的知道你花费到哪里去了吗?Python统计微信消费,生成微信消费账单。
  6. 主动变被动9个例句_语法知识:被动语态怎么用,你知道吗?
  7. 电路分析期中测试——个人题解
  8. 关注 | 摩尔定律到底还能走多远?
  9. Spring(2) —— 注入方式哪家强
  10. iOS备忘录之Xcode插件清理