一直不是 LSP(Language Server Protocol)的粉丝,总觉得配置比较麻烦,但最近
试用了 kickstart.nvim,LSP 开箱可用,感觉还是有一些帮助的。
kickstart.nvim 是一个单文件的 Neovim 配置文件,包含大量注释和最常用的插件配置。
最方便的在于可以自动安装缺失的插件。只要网络环境允许,安装了它的配置文件之后,
只要启动 nvim 就可以自动完成后续的配置。项目地址:kickstart.nvim 。
在安装了 kickstart.nvim 之后,立刻做了一些自己习惯键位的设置,并调整了部分插件,
的确感觉比较省心。我做的修改可以在我的 github 中找到:my nvim config 。
插件系统使用 Lazy.nvim,需要更新插件的时候可以执行 :Lazy
,根据菜单可以选择更新(Update)、
清理(Clean)等等。LSP 使用 Mason.nvim,也可以执行 :Mason
看到类似的菜单。
一个对新手很有帮助的插件是 which-key.nvim,可以通过浮动窗口提示可用的命令按键。
比如在命令状态下按下 g 键,它就会提示你后续可以按的按键,下面代码是部分提示内容:
d -> LSP: [G]to [D]efinition
D -> LSP: [G]to [D]eclaration
I -> LSP: [G]to [I]mplementation
LSP 的功能也比较强大,比如可以在整个工程内进行变量改名:<leader>rn
,还有一个是 Code Action,
通过 <leader>ca
启动,具体能实现的功能由 LSP 本身来决定。
不同 LSP 的配置还不同。比如在使用 lua_ls 的时候,用 Code Action 功能关闭了对某个建议的提示,
后续找了半天没有找到从哪里恢复设置。结果最后发现保存在了 ~/.config/.luarc.json
这个文件中。
而 pylsp 的设置需要在 nvim 的配置文件中进行修改。具体其它一些用法还要在将来逐渐领会。
让终端可以显示的更美观。
只从更换到 alacritty 作为主要的终端模拟器之后,一直对它很满意,唯一遇到的问题是部分字形无法
显示,例如 💻 是一个电脑的图标,但在我之前的终端上显示不出来。但这种字形平时很少遇到,网页
上显示也都正常,就一直没有管它。究其根源就是这些字形在我目前使用的字体文件中没有定义,所以
无法显示。
最近又试用了 ghostty,它却可以正常显示这些字形,于是萌生了提升 alacritty 体验的想法。经过调研
发现 alacritty 没有字体 fallback 的设置,只能依赖系统的设置。解决的办法就是创建一个字体配置文件:
.config/fontconfig/fonts.conf
,内容如下:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<alias>
<family> JetBrains Mono</family>
<prefer>
<family> JetBrains Mono</family>
<family> Noto Color Emoji</family>
</prefer>
</alias>
<alias>
<family> JetBrains Mono Bold</family>
<prefer>
<family> JetBrains Mono Bold</family>
<family> Noto Color Emoji</family>
</prefer>
</alias>
<alias>
<family> JetBrains Mono Italic</family>
<prefer>
<family> JetBrains Mono Italic</family>
<family> Noto Color Emoji</family>
</prefer>
</alias>
</fontconfig>
这里定义了我如果使用 JetBrains Mono
字体的时候,如果遇到不能显示的字形,就要使用
Noto Color Emoji
字体来显示。设置之后重启 alacritty 就可以正确显示之前缺失的字形了。
Noto Color Emoji
是我为了这次调整新安装的字体,不知道有什么办法可以知道 ghostty
使用的什么字体,ghostty 甚至不依赖系统的字体设置。
alacritty 对字体的 ligature 没有支持,ghostty 支持的就很好。
云平台上并没有 void 的镜像,本文记录如何在一个新安装的 arch 云主机上,安装并配置 void。
在 arch 主机上使用的是 btrfs 文件系统,这会大大简化分区操作。首先看一下当前配置:
pluto@arch4 ~ > sudo btrfs su l /
ID 256 gen 126 top level 5 path var/lib/portables
ID 257 gen 126 top level 5 path var/lib/machines
ID 258 gen 61 top level 5 path swap
前面两个应该是 systemd 建立,目前都是空的,swap 是虚拟内存空间,需要保留。
由于还准备保留 arch,双系统共用 home 会比较方便,所以建立一个 home 子卷。
pluto@arch4 ~ > sudo btrfs su cr /@home
Create subvolume '//@home'
pluto@arch4 ~ > sudo cp /home/* /@home/ -a
然后设置 /etc/fstab
挂载 home
分区,添加如下内容:
UUID= <your-btrfs-device-uuid> /home btrfs subvol= @home,defaults 0 0
注意如果 /home
目录的权限是 700 的话,普通用户无法访问个人目录,需要改成 755。
重新生成启动配置文件,检查生成的文件是否合理:
pluto@arch4 / > sudo grub-mkconfig -o /boot/grub/grub.cfg
接下来把 arch 的 文件系统做个快照,以后作为 arch 的根目录,同时建立一个 void 的根目录。
pluto@arch4 / > sudo btrfs su sn / /@archroot
Create snapshot of '/' in '//@archroot'
pluto@arch4 / > sudo rmdir @archroot/@home
pluto@arch4 / > sudo btrfs su cr /@voidroot
Create subvolume '//@voidroot'
重启后确认文件系统挂载没有问题,删除原来根文件系统中的内容:
pluto@arch4 / > sudo mount /dev/sda3 /mnt
pluto@arch4 ~ > sudo find /mnt -mindepth 1 -maxdepth 1 ! -name '@archroot' ! -name '@home' ! -name ' @voidroot ! -name swap -exec rm -rf {} +
此时必须重新安装一下 grub
,否则可能进入到 grub rescue 模式(刚刚犯了这个错误)
pluto@arch4 ~ > sudo grub-install --efi-directory= /efi
重启进入 arch 之后,挂载 @voidroot
目录:
pluto@arch4 ~ > sudo mount /dev/sda3 /mnt -o subvol= @voidroot
按照官方安装文档 安装 void。
需要注意的主要有以下几项:
允许 dhcpd 和 sshd 两个服务,否则重启之后可能无法连上主机。
bash-5.2# ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/
bash-5.2# ln -s /etc/sv/sshd /etc/runit/runsvdir/default/
不重复安装 grub,使用 arch 的启动管理器,在 /etc/grub.d/40_custom
中
填入如下内容。
menuentry 'Void Linux' {
set root= 'hd0,gpt3'
linux /@voidroot/boot/vmlinuz-6.6.59_1 root= UUID= <your-btrfs-device-uuid> rw rootflags= subvol= @voidroot loglevel= 3 quiet console= tty0 console= ttyS0,115200
initrd /@voidroot/boot/initramfs-6.6.59_1.img
}
由于共享 home 分区,添加用户,注意 uid 和 gid 是否相同。
注意用户的 sudoer 设置,使用户可以获得 root 权限。
双系统使用不同的 ssh key 会让客户端很麻烦,因此将 arch 系统中的 key 复制到 void 系统中。
void 更新了内核之后需要更新 grub 的配置。
在 arch 系统中,可以使用
sudo grub-reboot 'Void Linux'
来让系统在重启之后进入到 void 系统。但由于文件系统是 btrfs,grub 无法直接修改,使得之后每次
启动都会在 void 系统中。解决方法是在 void 中安装 grub 工具,不执行 grub-install
安装。
然后用 grub-editenv
修改 arch 的启动设置。
pluto@void ~ > sudo mount /dev/sda3 -o subvol= @archroot /mnt
pluto@void /mnt/boot/grub > grub-editenv grubenv set next_entry= 'Arch Linux'
这样就可以在重启后进入 arch 系统。
手持拍摄的视频总会抖动,使用 Linux 的现成工具就可以进行修补。
首先将视频转换为图像文件:
$ ffmpeg -i ../INPUT.MP4 DSC_%03d.png
从图像中找到一个子图像用来对比,尽量小一点的图像便于快速定位,但必要要保证
图像有一定的特点,可以在视频中唯一定位。
接下来利用 ImageMagick 进行子图像的定位:
$ compare -metric RMSE -subimage-search big.png sub.png k.png
其中命令中的最后一个参数是具有定位信息的结果图像,在这里可以忽略。
编写一个简单的命令脚本将每次的定位结果写入到文件中:
$ for i in DSC_* ; do compare -metric RMSE -subimage-search $i sub.png k.png 2>> log.txt; echo >> log.txt; done
$ cat log.txt | awk '{print $4}' > pos.txt
pos.txt 中的坐标值就是子图像在每个视频帧的位置,然后编写一个小脚本对视频帧进行
剪裁。这里我用了 python 以增加扩展性,也许将来可以把全部内容写到一个程序中。
最后用 ffmpeg 将图像再编码成视频。
$ ffmpeg -f image2 -i pic%03d.png test.mp4
校园一卡通是 Mifare 卡,一直想了解它的原理……
MIFARE 是 NXP 公司的商标,主要用于利用 NFC 技术通信的低成本ID/IC卡。
网上找相关标准比较复杂,还是从工程的角度入手。淘宝购入 ACR122U 芯片
的读卡器,然后用相关软件对卡进行操作来增加对卡的认识。
读卡器到手之后在 Linux 下面无法正常工作,dmesg 显示错误消息:
NFC: Couldn't poweron the reader (error -11)
以为是内核的问题,更新了 Debian 到最新版之后问题依旧。
换个思路,在 ACS 下载了最新的驱动,并安装相关软件:
# dpkg -i libacsccid1_1.1.5-1~bpo9+1_amd64.deb
# apt-get install pcscd pcsc-tools
结果运行 pcsc_scan 之后,读卡器的红灯亮起,竟然开始工作了。
不过这个软件读到的只是卡的属性,并看不到具体的数据,继续安装了 nfc 软件
# apt-get install libnfc5 libnfc-bin libnfc-dev
使用 nfc-list 也只能读到ATQA(属性),UID(第一扇区前四个字节)和SAK(?)。
还需要下载一个强力的软件 mfoc,通过暴力破解获取数据。下载源码编译之后,运行
就可以将数据完整读出了,但由于是暴力破解,所以需要的时间比较长。感觉
读一张卡片要 10 分钟左右,比 Windows 下面的软件要快一些,也更加稳定。
mfoc 读出数据的过程也把密钥获得了,将密钥保存到文件中,下次读卡的时候就会
快一些:
# ./mfoc -f keys.txt -O mycard.mfd
目前还有一个疑问,不同的校园卡用的密钥竟然不一样,这样如何管理呢?也许
密钥不唯一,暴力破解的时候就有可能得到不同的值,实际密钥会是不同的一个。
另外如果用校园卡做门禁,只要用到 UID 部分就可以,也不需要破解,速度很快。
由于我比较习惯使用 latex 写自己的各种文档,而提交的时候又往往需要 Word 格式,
有一个合适的转换器就变得非常必要了。
将 latex 转换成 Word 格式的需求不断涌现,印象比较深的是 2011 年提交文稿的那次。
当时也是找了很多工具,最后使用了 tex4ht 工具,将文稿转换为 html,然后用自己
写的一些过滤脚本进行处理,最后才导入 Word。整个过程是比较痛苦而且错误百出的,
结果直到今天依然没有非常理想的工具。
最近又有了难以躲过的转换格式需求,pandoc 软件进入了我的视野,通过查看手册
发现 pandoc 简直是一个万能转换器,而我只是尝试了对 doc 的支持。
用它转换文件格式非常容易,不用配置脚本也没有复杂的开关选项。对于转换 latex
到 docx 只要如下的命令:
$ pandoc -f latex -t docx source.tex -o output.docx
不用解释就可以了解这个命令的使用方法,而且给我的第一感觉就是非常的快,甚至
比使用 latex 生成 pdf 文件的速度还快。唯一发现的问题是表格支持不太好,但表格
在我的文档中使用不多,手动调整一下就好了。
这次的主要任务是转换科技论文,pandoc 又一次给我了惊喜,大部分公式和图片都
很好的进行转换,只有几个问题需要关注:
pdf 格式的文件支持不好,必须先转换为 png 格式。
matrix 公式支持不好
公式里面自定义的 argmax 命令不支持
公式和图没有编号
感觉 pandoc 并没有使用 latex 作为后端,而是用自己的解释器来分析文档,因此
稍微复杂一些的 latex 指令就无法支持了。虽然还没有尝试,估计 pgf 系列包都
不会支持的很好。
没有编号的问题比较大,交叉引用全部都失效了,这次我都通过手工修改了。网上看到
好像有过滤器可以做类似的事情,但语法格式都不是标准的 latex,我就只好放弃了。
我开始以为参考文献是不被支持的,结果一个简单的过滤器就可以解决一半问题。
$ sudo apt-get install pandoc-citeproc
$ pandoc -f latex -t docx source.tex --bibliography= mybib.bibtex -o output.docx
这样是可以生成参考文献,但是格式不符合要求。经过网络搜索才知道还需要一个
格式描述文件(citation style language)ieee.csl 。下载这个文件之后用如下命令就可以
搞定参考文献了。
$ pandoc -f latex -t docx source.tex --bibliography= mybib.bibtex --csl= ieee.csl -o output.docx
尝试一下机智云的软硬件环境
机智云是一个比较常用的物联网云平台,由于手上有相关的硬件,因此准备尝试一下。
GAgent 是机智云的固件产品,写入到 ESP8266 wifi 模块后可以简化物联网
wifi 上网的主要功能。烧写固件需要到乐鑫(Espressif)下载工具软件,并从
机智云下载固件映像。按照机智云上的固件烧写说明却无法连接成功。由于我
用的模块来自第三方,猜想是 GPIO0 的管脚位置不同,最后查了淘宝上的一款
ESP-12F 模块,才知道我的 GPIO0 在从指示灯开始数的第五个位置。
第一次烧还是不成功,报 efuse 错误,结果第二次烧就成功了。
使用调试助手和 wifi 模块连接上之后,点击模拟 V4MCU,则可以自动和 wifi 模块
通过串口协议通信。输入 product_key 之后,可以在界面上看到我在机智云上建立
的产品信息。
在手机端安装上机智云的产品调试 APP(登录有问题,用我注册的个人用户帐号好像
无法登录,不过可以跳过登录,不影响使用),在调试助手中打开指令界面,选择
AirLink按钮,然后在手机端输入 AP 的信息并搜索硬件。大概十几秒之后 wifi
模块就可以登录机智云了,在手机段也可以看到我的产品信息。
手机软件根据我设置的产品信息可以看到照明的按钮,我在手机上对这个按钮进行
操作就可以在调试助手中看到照明的数值被改变了,也就是基本实现了我所需要
的功能。
使用 Arduino 连接到串口 wifi 模块,比较麻烦的是每次下载代码必须把 wifi
模块拿掉,否则会干扰下载。按照示例的代码下载了之后,从 DEV 到 APP 的通道
没有问题。但从 APP 到 DEV 就是不行。通过机智云网上的日志可以看到,消息传递
没有问题,应该就是 Arduino 这边的代码问题了。
后来把检测是否有相关命令的 hasBeenSet 调用去掉,直接用 read 读取相应的值,
结果就正常了。顺便说一下机智云自带的调试 APP 和下载参考代码生成的 APP
都可以用,功能类似。(3月17日更新:这个部分后来发现还是我自己的代码问题)
后来想在 ESP8266 模块中写入 AT 固件,自己控制 WIFI 接入,但确多次无法成功。
网上下载的不同固件都无法正常启动,在 minicom 中只能看到乱码。后来看资料
指导启动信息的波特率是 74880,minicom 和 screen 都不支持,最后还是 esptool
中带的 miniterm.py 支持。
看到的错误原因是 csum err,但 verify_image 也没有问题,不知道原因是什么。
网上看到有人说用 dout 方式写入就没有问题了,可用 win 下面的官方写入软件
根本就写不进去,最后下载开源的 esptool 就可以用 dout 方式写入了,结果看到
错误信息不一样了,变成
2nd boot version : 1.7(5d6f877)
SPI Speed : 40MHz
SPI Mode : DOUT
SPI Flash Size & Map: 32Mbit(512KB+512KB)
jump to run user1 @ 1000
mismatch map 5,spi_size_map 4
system_partition_table_regist fail
还是看网上的信息,说 1.7 的固件会有这个问题,但 1.6.2 的就没有问题了。
真是历尽千辛万苦终于获得了 ready 提示信息。
虽然记录的过程看来很简单,但实际经过的尝试复杂的多。
总体感觉机智云上手还是比较容易的,从昨天看资料开始,全部用掉的时间估计在
4 个小时左右。要不是软件这边有一点坑,应该更快的可以完成设计。
Google 现在好像不太支持命令行工具了,android 命令即将废弃,好像
已经没有办法只用命令行工具完成 Android 开发了。
只安装了 SDK 之后其实离开始工作还有很大距离。运行 sdkmanager --list
可以看到能安装的组件,然后就可以用 sdkmanager
安装,例如
$ sdkmanager "emulator;platform-tools"
建立虚拟机可以用 avdmanager 命令,例如:
$ ./avdmanager create avd -n test2 -k "system-images;\
android-25;google_apis;arm64-v8a" -d "Galaxy Nexus"
其中 -d --device
参数在手册里面都没有提,在执行 create avd
命令的时候可以看到相关的提示。而可选的设备列表在 lib/devices.xml
文件中可以找到。
这个命令在执行的时候有可能报告 libGL 的加载失败,可以在运行前指定:
$ export ANDROID_EMULATOR_USE_SYSTEM_LIBS= 1
原来的 android create project
命令已经不被支持,目前只能使用 android
studio 建立工程。
给实验室的电脑装 Debian,记录几个遇到的问题
Debian 本来是非常熟悉了,但安装 stretch 的时候还是需要的几个问题
新安装的系统使用了新的命名规则,例如网络接口的名字变成了 enp0s31f6
这样就变得很不习惯,暂时没有发现这样的好处(命名唯一)。
可以使用 udev rule 来给接口改名字,但比较简单的还是增加一个内核参数,
修改 /etc/default/grub
GRUB_CMDLINE_LINUX= "net.ifnames=0 biosdevname=0"
当使用多系统的时候,可以保存上次的选项会比较方便,这里只是记录一下
方法,并不是很困难,还是修改 grub 文件
GRUB_DEFAULT= saved
GRUB_SAVEDEFAULT= true
ifconfig 命令缺省不安装了,取而代之的是功能更加强大的 ip 命令,
但这个命令还需要熟悉,如果要安装原来的命令,需要
$ sudo apt-get install net-tools
下面列出一些常用命令,便于以后记忆:
$ sudo ip addr add 192.168.0.51/24 dev eth0
$ ip addr show eth0
$ ip link
$ ip route show
$ sudo ip route add default via 192.168.0.1
$ ip neighbour # arp -a
$ sudo ip link set eth0 down
给实验室的电脑装 Windows,记录几个遇到的问题
安装 Windows 过程本身没有什么问题,但也许是太长时间没有用过
Windows 系统,后续安装软件和配置的时候遇到了一些问题。
系统安装完毕后需要运行激活客户端进行 KMS 激活,结果相关软件
确“无法运行”。结果是我太着急了,如果多等待一会就可以看到是
SmartScreen 把应用拦截了,由于网络还没有配置所以迟迟给不出
建议。解决方法要么关掉 SmartScreen,要么配置好网络。
这是一个迷惑我很久的问题。在实验室里面安装的一个 Windows
加上必备应用占用空间 30G 左右。而在我办公室安装的同样配置
竟然要多占用几个 G 的空间。过了几天我才发现,原来是办公室
的网络环境好,自动下载了 N 个应用,包括游戏和一些垃圾软件。
卸载之后应该就没有问题了。网上资料显示,如果要防止自动安装,
可以增加如下注册表项:
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CloudContent]
"DisableWindowsConsumerFeatures"=dword:00000001
部分电脑需要 Windows 和 Linux 共存,系统时间就成为影响使用
体验的一个麻烦。最好的办法还是让 Windows 使用 UTC 时间,也是要
修改注册表:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
"RealTimeIsUniversal"=qword:00000001
这个部分的看法有分歧,官方和国外好多地方都说有了 WindowsDefender
就不需要安装杀毒软件了。但这里我持保留态度,主要对微软不是很信任,
因此还是安装了 ESET,希望更专业一些。安装了 ESET 后 WindowsDefender
的杀毒功能就自动关闭了,应该也不会影响性能。