假设我正在tail
查看正在运行的应用程序的一些日志,我预计很快就会出现一些长输出,我希望在完成后滚动到顶部。tmux 有什么可以帮助我的东西吗?我在想像 vim 的分数,我可以按ma
做一个名为 的标记a
,然后按'a
跳转到该行。
理想的工作流程:
tail -f
一些东西<prefix> m a
树立一个标记a
- 做一些事情,导致大量的输出被记录下来
<prefix> ' a
跳转到a
定义的位置
答案1
虽然 Tmux 确实具有“标记”功能,但我认为它并不适合您的用例。
在复制模式下,按下Shiftx(又称“X”)会设置一个标记,然后Metax在当前位置和该标记之间切换。问题是,当你退出复制模式时,标记会丢失。所以你不能运行随后的 tail -f
并回到该点。
我个人的建议是使用分页器进行输出,该分页器支持 (a) 跟踪不断增长的文件,以及 (b) 标记/跳转功能。这可以在命令中轻松找到less
。您的工作流程将非常接近您所描述的:
less +F
一些东西- Ctrl+c暂时退出跟随模式
- ma设置一个名为“a”的标记
- F重新启动跟随模式
- 做一些事情,导致大量的输出被记录下来
- Ctrl+c暂时退出跟随模式(无论如何,您都不希望它在分析输出时滚动)。
- 'a跳到你的目标
- F如果需要,重新启动跟随模式
编辑/更新
如果你真的想要一个“标记”和“转到标记”功能,那么可能的, 但非常在我看来,这太 hacky 了。我发布这篇文章的原因其实只是因为 (a) 我终于让它 (大部分) 工作了,以及 (b) 我想把它从我的配置中移除,但又不想失去工作成果。
首先,创建两个单独的附加文件:
.tmux-set_mark.tmux
:
# Must use "run-shell" since it can run the
# command immediately. The #() syntax always
# uses the *previous* results.
# The capture-pane is hackery to get the current
# line number we are on (starting from the
# beginning of the history.
run "tmux set-environment TMUX_CUR_LINE $(tmux capture-pane -S - -E - -p | tac | awk 'NF {p=1} p' | wc -l)"
# Store it in a user-option on the current
# pane. This allows marks in multiple panes
# to work.
set-option -F -p @TMUX_MARK "#{TMUX_CUR_LINE}"
display-message "Mark set at line #{@TMUX_MARK}"
.tmux-goto_mark.tmux
:
# Must use "run-shell" since it can run
# the command immediately. The #()
# syntax always uses the *previous*
# results.
run-shell "tmux set-environment TMUX_CUR_LINE $(tmux capture-pane -S - -E - -p | tac | awk 'NF {p=1} p' | wc -l)"
# Set a user option on the pane with
# the line number we need to goto.
# This is calculated, of course, by
# subtracting the marked-line-number
# from the current-line-number
set-option -F -p @TMUX_GOTO "#{e|-:#{TMUX_CUR_LINE},#{@TMUX_MARK}}"
copy-mode
# Goto the line. Again `run-shell` is needed
# here since send-keys can't expand the FORMAT
# string, but run-shell can.
run-shell 'tmux display-message #{@TMUX_GOTO}'
run-shell 'tmux send-keys -X goto-line #{@TMUX_GOTO}'
# The next two lines are just additional
# hackery to use the built-in TMux marking
# ability so that the marked line is highlighted
# and at the top of the screen
send-keys -X set-mark
send-keys -X jump-to-mark
然后,在您的中.tmux.conf
设置键绑定以获取这些文件:
unbind x
bind x source-file "$HOME/.tmux-set_mark.tmux"
unbind X
bind X source-file "$HOME/.tmux-goto_mark.tmux"
在我看来,这太可怕了。更简单的方法失败了:
- 如果有更好的方法来获取缓冲区中当前所在的行号,那就简单多了,但似乎没有一个变量可以做到这一点。我能找到的最接近的方法是
history_size
,但直到您开始滚动窗格时,历史记录才会开始。 - 如果采用绝对行号会更容易
goto-line
,而不是采用相对行号底部复制模式下的缓冲区,而不是顶部。
此代码还有一个额外的警告/错误。如果您在 Tmux 窗格的第一个“页面”上执行此操作(在开始滚动之前),它突出显示的行将不是您标记的行。另一种方法是不使用:
send-keys -X set-mark
send-keys -X jump-to-mark
但随后,他们goto-line
总会把期望的标记放在底部窗格,这意味着您始终需要向下滚动窗格。
答案2
鉴于@NotTheDr01ds 对我在 OP 下方的评论的评论,您可以在开始步骤 3 中的进程之前,向您正在跟踪的文件中附加一个唯一的行(如果您具有写权限,并且附加这一行不会干扰该日志文件将来的任何使用),方法是:
echo '# mymark' >> file.log && tail -f file.log
tail -f
或者如果这不是首选,并且如果你要拖放的文件在你开始第 3 步的过程之前没有快速增长,你可以直接在终端中输入显示的输出
$ tail -f file.log
> some line from the log
> another line from the log
# mymark!
> line generated by step3
> and there will be many more lines generated by step3...
> . . . . .
> . . . . .
> . . . . .
# mymark
然后在这两种情况下,您都可以在 tmux 的复制模式(使用)中向后搜索字符串?^# mymark
。