Vim:将文本选择归档到其他文件中



我想创建一个命令和绑定,用于将选定的文本附加到另一个带有时间戳的文件中。我从其他帖子中收集了一些零碎的东西,但我几乎不知道自己在做什么,也没有得到我所期望的。

fun! MoveSelectedLinesToFile(filename)
exec "'<,'>w! >>" . a:filename
norm gvd
endfunc
fun! ArchiveSelectedLinesToFile(filename)
call writefile( ["[" . strftime("%Y-%m-%d %H:%M:%S") . "]"], a:filename, "a" )
call MoveSelectedLinesToFile(a:filename)
call writefile( ["",""], a:filename, "a" )
endfunc
vnoremap a :call ArchiveSelectedLinesToFile(expand('%:p') . '.arc.md')<CR>

在该内容的第4-6行的序列上使用:

1
2
3
4
5
6
7
8
9

存档文件显示:


[2022-09-19 14:52:10]

[2022-09-19 14:52:10]


而它应该显示

[2022-09-19 14:52:10]
4
5
6

并且源文件被更改为

1
2
3
8
9

这是7被错误地取下的一行。如果这意味着什么的话,我在Windows上。

Q:

  1. 我得到了ArchiveSelectedLinesToFile所有3行的E16无效范围错误。到底在哪里?为什么
  2. 有没有一种方法可以构建一个文本块并附加它,而不是逐个添加不同的位,比如时间戳和空白?让它成为一个连贯的操作?也许只麻烦管道机构一次
  3. 为什么这样不一致?有时,对于一个触发,我会在另一个文件中获得2个没有有效负载的时间戳,一旦它工作正常
  4. 有没有更简单的方法可以用这种方式或类似的方式进行归档

我知道这些可能都没有那么干净,但到目前为止我还不清楚。感谢对形式的改进建议。

背景:我最近开始使用VimWiki做笔记,包括我的TODO,如果你愿意的话,我的调用堆栈。我有一个主要的TODO文件,但是大型任务需要自己的文件。现在,每当我完成TODO时,我可能会在该TODO的标题下放更多的笔记,为未来的我保存有价值的信息。不用为这个主题创建一个额外的wiki条目,传统上我只是删除这些行,我开始认为将大部分内容存档会很好。我认为使用版本控制是过分的。通过将这些内容放入另一个带有时间戳的文件中,这就相当于一种历史记录。此外,我仍然可以在存档和删除之间进行选择,以决定哪些可能进一步相关,哪些不相关。

:help writefile()将列表作为第一个参数,因此更好的策略是先构建带有时间戳和all的列表,然后使用单个writefile()

为此,您需要从正确处理范围开始。当你在一个范围内调用这样定义的函数时,每行都会调用该函数:

function! Foo()
echo line('.')
endfunction
:4,6call Foo()
4
5
6

如果这是你的目标,那完全没问题,但这里不是这样。您希望函数被调用一次,因此需要使用range参数来定义它:

function! Foo() range
echo line('.')
endfunction
:4,6call Foo()
4

它允许你自己处理范围,在功能范围内:

function! Foo() range
echo a:firstline
echo a:lastline
endfunction
:4,6call Foo()
4
6

参见:help :func-range

首先生成时间戳:

function! ArchiveSelectedLinesToFile() range
let timestamp = '[' . strftime('%Y-%m-%d %H:%M:%S') . ']'
endfunction

第二步,将所选行存储在一个变量中:

function! ArchiveSelectedLinesToFile() range
let timestamp = '[' . strftime('%Y-%m-%d %H:%M:%S') . ']'
let lines = getline(a:firstline, a:lastline)
endfunction

参见:help getline()

第三,将它们放在一个列表中:

function! ArchiveSelectedLinesToFile() range
let timestamp = '[' . strftime('%Y-%m-%d %H:%M:%S') . ']'
let lines = getline(a:firstline, a:lastline)
let archival_data = [timestamp] + lines
endfunction

参见:help list-concatenation

第四次,将列表写入给定文件:

function! ArchiveSelectedLinesToFile(filename) range
let timestamp = '[' . strftime('%Y-%m-%d %H:%M:%S') . ']'
let lines = getline(a:firstline, a:lastline)
let archival_data = [timestamp] + lines
call writefile(archival_data, a:filename, 'a')
endfunction

第五行,删除所选行:

function! ArchiveSelectedLinesToFile(filename) range
let timestamp = '[' . strftime('%Y-%m-%d %H:%M:%S') . ']'
let lines = getline(a:firstline, a:lastline)
let archival_data = [timestamp] + lines
call writefile(archival_data, a:filename, 'a')
execute a:firstline . ',' . a:lastline . 'd _'
endfunction

参见:help :range:help :d:help "_

但是,由于所有以a开头的文本对象,您还没有完成。这将导致时间问题,因此您必须将函数调用映射到不同的键,而不是某些命令、运动或映射的开始。此外,您可能希望将映射限制为视觉模式。以下是<F5>、YMMV:的示例

xnoremap <F5> :call ArchiveSelectedLinesToFile(expand('%:p') . '.arc.md')<CR>

最新更新