跳到主要内容

· 阅读需 2 分钟

基础结构

一个典型的 Telescope action 由两部分组成:

  1. 映射注册 (Mapping Registration)
  2. 动作实现 (Action Implementation)

快速开始

1. 注册按键映射

telescope_builtin.find_files({
attach_mappings = function(prompt_bufnr, map)
-- 在这里注册你的按键映射
map("n", "dd", function()
my_custom_action(prompt_bufnr)
end)
return true
end,
})

2. 实现动作函数

function my_custom_action(prompt_bufnr)
-- 1. 获取当前 picker
local picker = action_state.get_current_picker(prompt_bufnr)

-- 2. 获取选中项
local selection = action_state.get_selected_entry()

-- 3. 实现具体功能
-- 例如删除、复制、移动等操作
end

常用 API

  • action_state.get_current_picker(prompt_bufnr): 获取当前 picker
  • action_state.get_selected_entry(): 获取选中项
  • picker:delete_selection(callback): 删除选中项
  • picker:get_selection(): 获取选择的内容

实用示例

删除文件

function delete_file(prompt_bufnr)
local picker = action_state.get_current_picker(prompt_bufnr)
picker:delete_selection(function(selection)
-- 执行删除操作
return os.remove(selection[1])
end)
end

预览文件

function preview_file(prompt_bufnr)
local selection = action_state.get_selected_entry()
-- 在新窗口中打开文件
vim.cmd('split ' .. selection[1])
end

· 阅读需 3 分钟

因为苹果出了 vision pro,看着我实在是想要体验一下。

其实我最想要的就是躺在床上网上冲浪,或者敲代码。这种头戴设备,然后好像可以提供超级多屏幕的方案就让我很想要。

那没办法,贫穷,我只有找了现在便宜的平替 Meta Quest 3 来试一试

体验

刚开始在国内过年的时候拿到的设备,在家里科学上网没办法成功激活,加上过年时间安排比较多,所以就一直放在那里了。现在到了新加坡,重新连上广域网,开始研究这个 quest 3 怎么用。

结论是还不错,差不多达到了我的期望值

游戏

讲游戏的人有很多,我就不讲了,节奏光剑确实不错

生产力

哈哈,我想要聊得多是这个东西其实主要有两个软件,我觉得让Quest3能够达到我的需求. 一个是 immersed, 一个是 fluid。

immersed

这个东西就是很不错啦,可以理解为电脑的外接屏幕,而且是很大的那种。

你可以在空间的任何地方放置它们,比如我躺在床上用,也是看着三个大屏幕,感觉还是很不错的。

我深度使用了几天,感觉清晰度还是不够,和物理屏幕比起来还是有点差距的。但是可用。

fluid

这个算是现阶段 Quest3 自带的浏览器的增强版,强在他的屏幕布局是更加自由的,而且清晰度拉满的,如果 immersed 能够达到这种清晰度,我觉得就很不错了。

这个软件的手部跟踪已经操作也做得非常自然(intuitive)了,是个不错的东西。

总结

就是还不错,花接近4000RMB体验空间计算的产品,而且对比起来,我感觉这是一个我买来不会吃灰的产品。

有点想转 VR 开发程序员了,哈哈哈,说不定是未来的方向呢。

特别是在用完 softspace 这个软件之后,感觉未来真的就是每个人带个便携式的 VR 眼睛,走在路上到处都是屏幕和广告

· 阅读需 1 分钟

最近好多项目都是 js/ts 生态的前后端,感觉要补习一下了,这一堆框架有点傻傻分不清楚。

image

了解了之后,打算将我用 golang 写的 undercontrol 换成这一套生态体系的实现

现在想法是现有逻辑迁移到 nest.js

· 阅读需 2 分钟

区别

  • 单引号('): 用于表示字符串文字。当您需要在SQL查询中包含字符串值时,您通常会将其放在单引号中。
  • 双引号("): 双引号主要用于标识数据库对象的标识符,如表名、列名、索引名等。使用双引号可以让您创建具有特殊字符或空格的标识符,或者与SQL关键字相同的标识符。

Demo

  1. create a strange table
CREATE TABLE "MyTable" (
"Column1 with space" integer,
"Column2-with-dash" varchar(50),
"Column#3" date,
"Column$4" boolean,
"Column%5" numeric(10,2)
);
  1. insert some data
INSERT INTO "MyTable" ("Column1 with space", "Column2-with-dash", "Column#3", "Column$4", "Column%5")
VALUES (1, 'Value1', '2024-02-03', true, 100.50);

INSERT INTO "MyTable" ("Column1 with space", "Column2-with-dash", "Column#3", "Column$4", "Column%5")
VALUES (2, 'Value2', '2024-02-04', false, 200.75);
  1. query the data
SELECT * FROM MyTable;
  1. alter table
ALTER TABLE "MyTable"
ADD COLUMN "order" integer;
  1. query the data
SELECT order FROM MyTable; -- error
SELECT "order" FROM MyTable; -- correct

· 阅读需 1 分钟

UTM 是一个功能齐全的系统模拟器和虚拟机主机,适用于 iOS 和 macOS。它基于 QEMU。简而言之,它允许您在 Mac、iPhone 和 iPad 上运行 Windows、Linux 等。更多信息请访问 https://getutm.app/https://mac.getutm.app/。

Snapshot

今天想在虚拟机上搞点骚操作,但是又觉得搞坏了从头重新弄一个太费时间了,就去看看怎么操作 snapshot,发现好像咩有直接很用户友好的GUI上实现这个功能

但是幸好 可以通过命令 直接达到效果,也够我使用了

# create an snapshot
$ qemu-img snapshot F89035CE-DEF9-49D7-97F8-7EC0C2F3F9D9.qcow2 -c snapshot1

# list out all the snapshot
$ qemu-img snapshot F89035CE-DEF9-49D7-97F8-7EC0C2F3F9D9.qcow2 -l

More info: https://github.com/utmapp/UTM/issues/5484

· 阅读需 2 分钟

You can find the runnable code at this github repo

You can find the video tutorial at bilibili

Mock Static Method

@Nested
inner class MockStaticMethod {
private val now = LocalDateTime.of(2023, 3, 3, 0 ,0)

@Test
fun `should return mocked datetime`() {
mockkStatic(LocalDateTime::class)
every { LocalDateTime.now() } returns now

println(LocalDateTime.now()) // 2023-03-03T00:00

unmockkAll()
}
}

Mock Extension Function

class MockExtensionFunction(private val lintao: Lintao) {
fun bar() = lintao.extensionFunc()
}

class Lintao

fun Lintao.extensionFunc() = "ExtensionFunc"

class MockExtensionMethod {
private val lintaoMock = mockk<Lintao>()
private val target = MockExtensionFunction(lintaoMock)

@Test
fun test() {
mockkStatic(Lintao::extensionFunc) {
every { lintaoMock.extensionFunc() } returns "mocked function"

val result = target.bar()

assertThat(result).isEqualTo("mocked function")
}
}
}

Mock Companion object

class MockCompanion {
fun bar() = LintaoCompanion.foo()
}

class LintaoCompanion {
companion object {
fun foo() = "Haha"
}
}

class MockCompanionTest {
private val target = MockCompanion()

@Test
fun `should return mocked value`() {
println(target.bar()) // Haha
mockkObject(LintaoCompanion)
// mockkObject(LintaoCompanion::class) 这种写法是错误的,不能加 `::class`
every { LintaoCompanion.foo() } returns "mocked value"

val bar = target.bar()

assertThat(bar).isEqualTo("mocked value")
}
}

AndThen

class VerifySecondCall(private val dependency: MyDependency) {
// there're two calls of function bar
fun foo(): String {
return dependency.bar("arg1") + dependency.bar("arg2")

}
}

class MyDependency {
fun bar(arg1: String) = "Before mock: Call with $arg1"
}

class TestDrive() {
@Test
fun `some test`() {
val mockDependency = mockk<MyDependency>()
every { mockDependency.bar(any()) } returns "mock1" andThen "mock2"

val result = VerifySecondCall(mockDependency).foo()

assertThat(result).isEqualTo("mock1" + "mock2")
verify {
mockDependency.bar(withArg { assertThat(it).isEqualTo("arg1") })
mockDependency.bar(withArg { assertThat(it).isEqualTo("arg2") })
}
}
}

Spyk

class UseSpky() {
fun foo(): String {
throw RuntimeException("Foo")
}

fun anotherFoo(): String {
return "anotherFoo"
}
}

class TestDrive1 {

@Test
fun `use spyk by normal constructor`() {
val useSpky = spyk(UseSpky())
every { useSpky.foo() } returns "mock"

val fooResult = useSpky.foo()
// this method returns the mocked value, didn't throw the error, which means the real implementation didn't run at all.
assertThat(fooResult).isEqualTo("mock")

val anotherFooResult = useSpky.anotherFoo()
// this method returns the real value,
assertThat(anotherFooResult).isEqualTo("anotherFoo")
}
}

· 阅读需 2 分钟

安装与配置

https://github.com/junegunn/fzf?tab=readme-ov-file#installation

点进去这个连接,repo 里面写得很清楚了

基础使用方法

https://github.com/LintaoAmons/easy-commands.nvim 下面所有命令都是在这个仓库下进行的 如果你想跟着敲一遍,可以 clone 到本地动手试试

直接敲 fzf

fzf

实际上执行的是

find * -type f | fzf

上个命令的结果交给 fzf 进行搜索

搜索文档内容

cat CommandUsecase.md | fzf

有点类似 interactive 版本的 rg

rg -N '##' CommandUsecase.md

搜索本文件夹内容

ls . | fzf

将 fzf 的结果用在别的命令上

Command expansion

打开 fzf 找到的结果

open $(fzf)

将 fzf 找到的结果放到 clipboard 下次随时粘贴

fzf | tr -d '\n' | tee >(pbcopy)

选择多个结果

fzf --multi --bind='ctrl-a:select-all'
cat CommandUsecase.md | fzf --multi --bind='ctrl-a:select-all' 
cat CommandUsecase.md | fzf --layout=reverse --multi --bind='ctrl-a:select-all' | pbcopy

实用搜索Tips

查看帮助文档

fzf -h | fzf

大小写敏感

cat CommandUsecase.md | fzf +i

严格匹配

在需要搜索的内容前面加个 ',就是告诉fzf,严格匹配这个pattern

And

空格

Or

|

以XX开头

^

以XX结尾

$

取反

!

THX:https://thevaluable.dev/practical-guide-fzf-example/